Seregon/rtnet-stack

Real-Time Embedded Network Stack

C/66 B/No license
docs/integration.md
rtnet-stack / docs / integration.md
1# RT Network Stack - Integration Guide
2 
3**Version:** 1.0.0
4**Target Audience:** Embedded Systems Engineers
5**Prerequisites:** ARM Cortex-M4 knowledge, basic TCP/IP understanding
6 
7---
8 
9## 📋 TABLE OF CONTENTS
10 
111. [Quick Start](#1-quick-start)
122. [Platform Integration](#2-platform-integration)
133. [Configuration](#3-configuration)
144. [Usage Examples](#4-usage-examples)
155. [Best Practices](#5-best-practices)
166. [Troubleshooting](#6-troubleshooting)
177. [Performance Tuning](#7-performance-tuning)
188. [Migration From Other Stacks](#8-migration-from-other-stacks)
199. [Production Checklist](#9-production-checklist)
2010. [Support & Resources](#10-support--resources)
21 
22---
23 
24## 1. QUICK START
25 
26### 1.1 Minimal Example
27 
28```c
29#include "rtnet_stack.h"
30 
31/* Define your addresses */
32static const RTNET_IPv6Addr_t my_ipv6 = {
33 .addr = {0xFE, 0x80, 0, 0, 0, 0, 0, 0,
34 0x02, 0x00, 0x5E, 0xFF, 0xFE, 0x00, 0x53, 0x00}
35};
36 
37static const RTNET_MACAddr_t my_mac = {
38 .addr = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55}
39};
40 
41int main(void)
42{
43 /* 1. Initialize hardware */
44 HAL_Init();
45 SystemClock_Config();
46 Ethernet_Init();
47
48 /* 2. Initialize network stack */
49 if (RTNET_Initialize(&my_ipv6, &my_mac) != RTNET_OK) {
50 Error_Handler();
51 }
52
53 /* 3. Add default route */
54 RTNET_IPv6Addr_t gateway = {
55 .addr = {0xFE, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
56 };
57 RTNET_AddRoute(NULL, 0, &gateway, 10);
58
59 /* 4. Main loop */
60 while (1) {
61 RTNET_PeriodicTask(); /* Call every 100ms */
62 HAL_Delay(100);
63 }
64}
65 
66/* Ethernet RX interrupt handler */
67void ETH_IRQHandler(void)
68{
69 uint8_t packet[RTNET_MTU_SIZE];
70 uint16_t length;
71
72 if (Ethernet_ReceivePacket(packet, &length)) {
73 RTNET_ProcessRxPacket(packet, length);
74 }
75}
76```
77 
78---
79 
80## 2. PLATFORM INTEGRATION
81 
82### 2.1 Required Platform Hooks
83 
84You must implement these functions in your BSP:
85 
86```c
87/**
88 * @brief Enter critical section (disable interrupts)
89 * @note Must be reentrant (count nesting depth)
90 */
91void RTNET_CriticalSectionEnter(void)
92{
93 __disable_irq(); /* Or use FreeRTOS taskENTER_CRITICAL() */
94}
95 
96/**
97 * @brief Exit critical section (enable interrupts)
98 */
99void RTNET_CriticalSectionExit(void)
100{
101 __enable_irq(); /* Or use FreeRTOS taskEXIT_CRITICAL() */
102}
103 
104/**
105 * @brief Get monotonic timestamp in milliseconds
106 * @return Current time (wraps at UINT32_MAX)
107 */
108uint32_t RTNET_GetTimeMs(void)
109{
110 return HAL_GetTick(); /* Or FreeRTOS xTaskGetTickCount() */
111}
112 
113/**
114 * @brief Transmit packet via Ethernet hardware
115 * @param data Packet data (includes Ethernet header)
116 * @param length Total packet length
117 */
118void RTNET_HardwareTransmit(const uint8_t* data, uint16_t length)
119{
120 Ethernet_Transmit(data, length);
121
122 /* With DMA (preferred): */
123 // DMA_Transfer(&ETH_DMA_TxDesc, data, length);
124 // ETH->DMATPDR = 0; /* Trigger transmission */
125}
126```
127 
128---
129 
130### 2.2 Interrupt Configuration
131 
132**Priority Recommendations:**
133 
134| Interrupt | Priority | Notes |
135|-----------|----------|-------|
136| Ethernet RX | 5 | Medium priority |
137| SysTick (timer) | 15 | Lowest priority |
138| Critical control | 0-4 | Higher than network |
139 
140**Example (STM32):**
141 
142```c
143void NVIC_Config(void)
144{
145 HAL_NVIC_SetPriority(ETH_IRQn, 5, 0);
146 HAL_NVIC_EnableIRQ(ETH_IRQn);
147}
148```
149 
150---
151 
152### 2.3 Memory Layout
153 
154**Linker Script Recommendations:**
155 
156```ld
157/* Place network buffers in fast RAM (CCM on STM32F4) */
158.network_buffers (NOLOAD) :
159{
160 . = ALIGN(4);
161 _network_buffers_start = .;
162 *(.network_buffers)
163 . = ALIGN(4);
164 _network_buffers_end = .;
165} >CCMRAM
166 
167/* Or use DMA-accessible RAM */
168.dma_buffers (NOLOAD) :
169{
170 . = ALIGN(4);
171 *(.dma_buffers)
172} >SRAM1
173```
174 
175**In code:**
176 
177```c
178/* For zero-copy DMA */
179__attribute__((section(".dma_buffers")))
180static RTNET_Buffer_t g_dma_rx_buffers[RTNET_MAX_RX_BUFFERS];
181```
182 
183---
184 
185## 3. CONFIGURATION
186 
187### 3.1 Compile-Time Options
188 
189Edit `rtnet_stack.h`:
190 
191```c
192/* Reduce memory footprint for small MCUs */
193#define RTNET_MAX_RX_BUFFERS 4U /* Was: 8 */
194#define RTNET_MAX_TCP_CONNECTIONS 2U /* Was: 4 */
195#define RTNET_MAX_ROUTING_ENTRIES 16U /* Was: 32 */
196 
197/* Increase for high-throughput applications */
198#define RTNET_TCP_WINDOW_SIZE 8192U /* Was: 4096 */
199#define RTNET_MAX_TX_BUFFERS 16U /* Was: 8 */
200```
201 
202---
203 
204### 3.2 Runtime Configuration
205 
206```c
207/* Adjust QoS priorities based on application */
208typedef enum {
209 APP_QOS_CONTROL = RTNET_QOS_CRITICAL, /* 0 */
210 APP_QOS_TELEMETRY = RTNET_QOS_HIGH, /* 1 */
211 APP_QOS_BULK_DATA = RTNET_QOS_NORMAL, /* 2 */
212 APP_QOS_LOGGING = RTNET_QOS_LOW /* 3 */
213} App_QoS_t;
214```
215 
216---
217 
218## 4. USAGE EXAMPLES
219 
220### 4.1 UDP Client (Sending Data)
221 
222```c
223void send_sensor_reading(float temperature, float humidity)
224{
225 RTNET_IPv6Addr_t server = {
226 .addr = {0x20, 0x01, 0x0D, 0xB8, /* ... */ }
227 };
228
229 /* Format payload */
230 char payload[64];
231 snprintf(payload, sizeof(payload),
232 "{\"temp\":%.2f,\"hum\":%.2f}", temperature, humidity);
233
234 /* Send UDP packet */
235 RTNET_Error_t err = RTNET_UDP_Send(
236 &server,
237 5000, /* dest port */
238 0, /* auto-assign src port */
239 (const uint8_t*)payload,
240 strlen(payload),
241 RTNET_QOS_NORMAL
242 );
243
244 if (err != RTNET_OK) {
245 printf("UDP send failed: %d\n", err);
246 }
247}
248```
249 
250---
251 
252### 4.2 UDP Server (Receiving Data)
253 
254```c
255/* Register callback for UDP port */
256void udp_receive_callback(const uint8_t* payload, uint16_t length,
257 const RTNET_IPv6Addr_t* src_addr, uint16_t src_port)
258{
259 /* Process received data */
260 printf("Received %u bytes from port %u\n", length, src_port);
261
262 /* Echo back */
263 RTNET_UDP_Send(src_addr, src_port, 5000, payload, length, RTNET_QOS_NORMAL);
264}
265 
266/* In your initialization */
267RTNET_UDP_RegisterCallback(5000, udp_receive_callback);
268```
269 
270---
271 
272### 4.3 TCP Client
273 
274```c
275void http_get_request(void)
276{
277 RTNET_IPv6Addr_t web_server = {
278 .addr = {0x20, 0x01, 0x04, 0x70, /* ... */}
279 };
280
281 uint8_t conn_id;
282
283 /* 1. Connect */
284 RTNET_Error_t err = RTNET_TCP_Connect(&web_server, 80, &conn_id);
285 if (err != RTNET_OK) {
286 printf("TCP connect failed\n");
287 return;
288 }
289
290 /* 2. Send HTTP request */
291 const char* request = "GET / HTTP/1.1\r\nHost: example.com\r\n\r\n";
292 err = RTNET_TCP_Send(conn_id, (const uint8_t*)request, strlen(request));
293 if (err != RTNET_OK) {
294 printf("TCP send failed\n");
295 RTNET_TCP_Close(conn_id);
296 return;
297 }
298
299 /* 3. Receive response (callback-based) */
300 /* ... handled by registered TCP receive callback ... */
301
302 /* 4. Close connection */
303 RTNET_TCP_Close(conn_id);
304}
305```
306 
307---
308 
309### 4.4 mDNS Service Discovery
310 
311```c
312void discover_http_servers(void)
313{
314 RTNET_mDNSRecord_t record;
315
316 RTNET_Error_t err = RTNET_mDNS_Query("_http._tcp.local", &record);
317
318 if (err == RTNET_OK) {
319 printf("Found HTTP server: %s at port %u\n",
320 record.service_name, record.port);
321
322 /* Connect to discovered service */
323 uint8_t conn_id;
324 RTNET_TCP_Connect(&record.ipv6_addr, record.port, &conn_id);
325 } else {
326 printf("No HTTP servers found\n");
327 }
328}
329 
330void announce_device_service(void)
331{
332 /* Announce our device on the network */
333 RTNET_mDNS_Announce("_device-control._tcp.local", 8080, 3600);
334}
335```
336 
337---
338 
339### 4.5 Routing Table Management
340 
341```c
342void configure_routing(void)
343{
344 /* Link-local prefix (fe80::/10) - auto-added by stack */
345
346 /* Add route to corporate network */
347 RTNET_IPv6Addr_t corp_network = {
348 .addr = {0x20, 0x01, 0x0D, 0xB8, 0x00, 0x01, /* ... */}
349 };
350 RTNET_IPv6Addr_t corp_gateway = {
351 .addr = {0xFE, 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x01}
352 };
353 RTNET_AddRoute(&corp_network, 64, &corp_gateway, 10);
354
355 /* Add route to IoT subnet */
356 RTNET_IPv6Addr_t iot_network = {
357 .addr = {0xFD, 0x00, 0x00, 0x01, /* ULA prefix */ }
358 };
359 RTNET_AddRoute(&iot_network, 48, NULL, 5); /* Directly connected */
360}
361```
362 
363---
364 
365## 5. BEST PRACTICES
366 
367### 5.1 Error Handling
368 
369**Always check return values:**
370 
371```c
372RTNET_Error_t err = RTNET_UDP_Send(...);
373 
374switch (err) {
375 case RTNET_OK:
376 break;
377
378 case RTNET_ERR_NO_BUFFER:
379 /* Retry after delay or drop packet */
380 printf("TX buffer full, retrying...\n");
381 HAL_Delay(10);
382 break;
383
384 case RTNET_ERR_NO_ROUTE:
385 /* Trigger route discovery or alert operator */
386 printf("No route to destination\n");
387 break;
388
389 default:
390 printf("Unexpected error: %d\n", err);
391 break;
392}
393```
394 
395---
396 
397### 5.2 QoS Priority Guidelines
398 
399```c
400/* Real-time control (< 10ms latency required) */
401RTNET_UDP_Send(..., RTNET_QOS_CRITICAL);
402 
403/* Time-sensitive telemetry (< 100ms acceptable) */
404RTNET_UDP_Send(..., RTNET_QOS_HIGH);
405 
406/* Bulk file transfer */
407RTNET_TCP_Send(...); /* Defaults to RTNET_QOS_NORMAL */
408 
409/* Background logging */
410RTNET_UDP_Send(..., RTNET_QOS_LOW);
411```
412 
413---
414 
415### 5.3 Periodic Task Scheduling
416 
417```c
418/* RTOS-based scheduling (recommended) */
419void NetworkTaskFunction(void *pvParameters)
420{
421 TickType_t xLastWakeTime = xTaskGetTickCount();
422 const TickType_t xFrequency = pdMS_TO_TICKS(100);
423
424 for (;;) {
425 RTNET_PeriodicTask();
426 vTaskDelayUntil(&xLastWakeTime, xFrequency);
427 }
428}
429 
430/* Create task with appropriate priority */
431xTaskCreate(NetworkTaskFunction, "NetTask", 512, NULL,
432 tskIDLE_PRIORITY + 2, NULL);
433```
434 
435```c
436/* Bare-metal scheduling */
437void SysTick_Handler(void)
438{
439 static uint32_t tick_count = 0;
440
441 tick_count++;
442 if (tick_count >= 100) { /* Every 100ms */
443 RTNET_PeriodicTask();
444 tick_count = 0;
445 }
446}
447```
448 
449---
450 
451### 5.4 Statistics Monitoring
452 
453```c
454void monitor_network_health(void)
455{
456 RTNET_Statistics_t stats;
457 RTNET_GetStatistics(&stats);
458
459 /* Calculate error rates */
460 float rx_error_rate = (float)stats.rx_errors / stats.rx_packets;
461 float tx_error_rate = (float)stats.tx_errors / stats.tx_packets;
462
463 /* Alert if error rate exceeds threshold */
464 if (rx_error_rate > 0.01f) { /* 1% */
465 printf("WARNING: High RX error rate: %.2f%%\n", rx_error_rate * 100);
466 }
467
468 /* Log statistics periodically */
469 printf("Network Stats: RX=%lu TX=%lu Errors=%lu\n",
470 stats.rx_packets, stats.tx_packets,
471 stats.rx_errors + stats.tx_errors);
472}
473```
474 
475---
476 
477## 6. TROUBLESHOOTING
478 
479### 6.1 Common Issues
480 
481#### ❌ No Packets Received
482 
483**Symptoms:** `stats.rx_packets` remains 0
484 
485**Checklist:**
4861. Verify Ethernet PHY link is up: `ETH->MACMIIAR & ETH_MACMIIAR_MB`
4872. Check interrupt configuration: `NVIC->ISER[ETH_IRQn >> 5]`
4883. Verify `RTNET_ProcessRxPacket` is called from ISR
4894. Check IPv6 address configuration (must be link-local or globally routable)
490 
491```c
492/* Debug: Check if interrupts are firing */
493void ETH_IRQHandler(void)
494{
495 static volatile uint32_t irq_count = 0;
496 irq_count++; /* Set breakpoint here */
497
498 /* ... rest of handler ... */
499}
500```
501 
502---
503 
504#### ❌ Packets Sent But Not Received by Peer
505 
506**Symptoms:** `stats.tx_packets` increases, but peer doesn't receive
507 
508**Checklist:**
5091. Verify routing table has entry for destination
5102. Check neighbor cache has MAC address mapping
5113. Use Wireshark to capture packets on wire
5124. Verify checksums (disable HW checksum offload for debugging)
513 
514```c
515/* Debug: Dump TX packets */
516void RTNET_HardwareTransmit(const uint8_t* data, uint16_t length)
517{
518 printf("TX packet (%u bytes): ", length);
519 for (uint16_t i = 0; i < (length < 64 ? length : 64); i++) {
520 printf("%02X ", data[i]);
521 }
522 printf("\n");
523
524 Ethernet_Transmit(data, length);
525}
526```
527 
528---
529 
530#### ❌ Stack Overflow / Hard Fault
531 
532**Symptoms:** Intermittent crashes in `RTNET_ProcessRxPacket`
533 
534**Causes:**
5351. Insufficient stack size for network task
5362. Interrupt nesting exceeds stack limit
5373. Recursive calls (should never happen in this stack)
538 
539**Solutions:**
540```c
541/* Increase task stack size */
542xTaskCreate(NetworkTask, "Net", 1024, NULL, /* was 512 */
543 tskIDLE_PRIORITY + 2, NULL);
544 
545/* Reduce interrupt nesting */
546NVIC_SetPriority(ETH_IRQn, 6); /* Lower priority */
547 
548/* Monitor stack usage */
549UBaseType_t stackHighWaterMark = uxTaskGetStackHighWaterMark(NULL);
550printf("Stack free: %lu words\n", stackHighWaterMark);
551```
552 
553---
554 
555### 6.2 Debugging Tools
556 
557#### Enable Stack Assertions
558 
559```c
560/* In rtnet_stack.h */
561#define RTNET_ENABLE_ASSERTIONS 1
562 
563#if RTNET_ENABLE_ASSERTIONS
564#define RTNET_ASSERT(cond) \
565 do { \
566 if (!(cond)) { \
567 printf("Assertion failed: %s:%d\n", __FILE__, __LINE__); \
568 while(1); \
569 } \
570 } while(0)
571#else
572#define RTNET_ASSERT(cond) ((void)0)
573#endif
574```
575 
576---
577 
578#### Packet Capture to SD Card
579 
580```c
581void log_packet_to_sd(const uint8_t* data, uint16_t length, bool is_rx)
582{
583 FIL file;
584 f_open(&file, "packets.pcap", FA_WRITE | FA_OPEN_APPEND);
585
586 /* Write PCAP record header */
587 /* ... */
588
589 /* Write packet data */
590 UINT bytes_written;
591 f_write(&file, data, length, &bytes_written);
592
593 f_close(&file);
594}
595 
596/* In RX path */
597RTNET_Error_t RTNET_ProcessRxPacket(const uint8_t* data, uint16_t length)
598{
599 #ifdef RTNET_DEBUG_PCAP
600 log_packet_to_sd(data, length, true);
601 #endif
602
603 /* ... rest of processing ... */
604}
605```
606 
607---
608 
609## 7. PERFORMANCE TUNING
610 
611### 7.1 Optimize for Latency
612 
613```c
614/* Minimize interrupt latency */
615void SystemInit(void)
616{
617 /* Set all interrupts to lowest priority */
618 for (int i = 0; i < 8; i++) {
619 NVIC->IP[i] = 0xFF;
620 }
621
622 /* Ethernet RX highest priority (except critical control) */
623 NVIC_SetPriority(ETH_IRQn, 1);
624}
625 
626/* Use smallest buffer sizes */
627#define RTNET_MAX_RX_BUFFERS 4
628#define RTNET_MAX_TX_BUFFERS 4
629 
630/* Disable non-critical features */
631#define RTNET_ENABLE_MDNS 0
632```
633 
634---
635 
636### 7.2 Optimize for Throughput
637 
638```c
639/* Increase buffer counts */
640#define RTNET_MAX_RX_BUFFERS 16
641#define RTNET_MAX_TX_BUFFERS 16
642 
643/* Increase TCP window */
644#define RTNET_TCP_WINDOW_SIZE 16384
645 
646/* Enable hardware checksum offload */
647ETH->MACCR |= ETH_MACCR_IPCO; /* IPv4 checksum offload */
648 
649/* Use DMA burst mode */
650ETH->DMABMR |= ETH_DMABMR_USP | (32 << 8); /* 32-word burst */
651```
652 
653---
654 
655### 7.3 Optimize for Power Consumption
656 
657```c
658/* Minimize wake-ups */
659#define RTNET_MAX_RX_BUFFERS 2
660#define RTNET_MAX_TX_BUFFERS 2
661 
662/* Increase periodic task interval */
663void LowPowerNetworkTask(void)
664{
665 for (;;) {
666 RTNET_PeriodicTask();
667 vTaskDelay(pdMS_TO_TICKS(500)); /* Was 100ms */
668 }
669}
670 
671/* Use Ethernet Wake-on-LAN */
672ETH->MACPMTCSR |= ETH_MACPMTCSR_WFE; /* Wake on magic packet */
673```
674 
675---
676 
677## 8. MIGRATION FROM OTHER STACKS
678 
679### 8.1 From lwIP
680 
681| lwIP | RT Network Stack |
682|------|------------------|
683| `tcp_new()` | `RTNET_TCP_Connect()` |
684| `tcp_write()` | `RTNET_TCP_Send()` |
685| `tcp_close()` | `RTNET_TCP_Close()` |
686| `udp_new()` | N/A (stateless) |
687| `udp_send()` | `RTNET_UDP_Send()` |
688| `ip6addr_t` | `RTNET_IPv6Addr_t` |
689 
690---
691 
692### 8.2 From Zephyr
693 
694| Zephyr | RT Network Stack |
695|--------|------------------|
696| `net_context_connect()` | `RTNET_TCP_Connect()` |
697| `net_context_send()` | `RTNET_UDP_Send()` |
698| `net_if_ipv6_addr_add()` | `RTNET_Initialize()` |
699| `net_route_add()` | `RTNET_AddRoute()` |
700 
701---
702 
703## 9. PRODUCTION CHECKLIST
704 
705Before deploying to production:
706 
707- [ ] All platform hooks implemented correctly
708- [ ] Interrupt priorities configured properly
709- [ ] Stack sizes verified (use high-water-mark monitoring)
710- [ ] Error handling implemented for all network calls
711- [ ] Statistics monitoring in place
712- [ ] Watchdog timer configured
713- [ ] WCET verified on target hardware
714- [ ] Full system tested with production traffic
715- [ ] Backup/failover networking strategy defined
716- [ ] Security review completed (if applicable)
717- [ ] Documentation updated with deployment specifics
718 
719---
720 
721## 10. SUPPORT & RESOURCES
722 
723### Documentation
724- API Reference: `docs/api_reference.md`
725- Architecture Guide: `docs/architecture.md`
726- Verification Report: `docs/VERIFICATION_REPORT.md`
727 
728### Examples
729- `/examples/udp_echo_server`
730- `/examples/tcp_http_client`
731- `/examples/mdns_discovery`
732- `/examples/desktop_demo`
733 
734### Community
735- GitHub Issues: [https://github.com/seregonwar/rtnet-stack/issues](https://github.com/seregonwar/rtnet-stack/issues)
736 
737---
738 
739**Document Version:** 1.0.0
740**Last Updated:** 2026-01-08
741**Maintainer:** Seregonwar
742