Real-Time Embedded Network Stack
| 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 | |
| 11 | 1. [Quick Start](#1-quick-start) |
| 12 | 2. [Platform Integration](#2-platform-integration) |
| 13 | 3. [Configuration](#3-configuration) |
| 14 | 4. [Usage Examples](#4-usage-examples) |
| 15 | 5. [Best Practices](#5-best-practices) |
| 16 | 6. [Troubleshooting](#6-troubleshooting) |
| 17 | 7. [Performance Tuning](#7-performance-tuning) |
| 18 | 8. [Migration From Other Stacks](#8-migration-from-other-stacks) |
| 19 | 9. [Production Checklist](#9-production-checklist) |
| 20 | 10. [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 */ |
| 32 | static 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 | |
| 37 | static const RTNET_MACAddr_t my_mac = { |
| 38 | .addr = {0x00, 0x11, 0x22, 0x33, 0x44, 0x55} |
| 39 | }; |
| 40 | |
| 41 | int 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 */ |
| 67 | void 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 | |
| 84 | You 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 | */ |
| 91 | void RTNET_CriticalSectionEnter(void) |
| 92 | { |
| 93 | __disable_irq(); /* Or use FreeRTOS taskENTER_CRITICAL() */ |
| 94 | } |
| 95 | |
| 96 | /** |
| 97 | * @brief Exit critical section (enable interrupts) |
| 98 | */ |
| 99 | void 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 | */ |
| 108 | uint32_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 | */ |
| 118 | void RTNET_HardwareTransmit(const uint8_t* data, uint16_t length) |
| 119 | { |
| 120 | Ethernet_Transmit(data, length); |
| 121 | |
| 122 | /* With DMA (preferred): */ |
| 123 | // DMA_Transfer(Ð_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 |
| 143 | void 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"))) |
| 180 | static 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 | |
| 189 | Edit `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 */ |
| 208 | typedef 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 |
| 223 | void 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 */ |
| 256 | void 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 */ |
| 267 | RTNET_UDP_RegisterCallback(5000, udp_receive_callback); |
| 268 | ``` |
| 269 | |
| 270 | --- |
| 271 | |
| 272 | ### 4.3 TCP Client |
| 273 | |
| 274 | ```c |
| 275 | void 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 |
| 312 | void 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 | |
| 330 | void 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 |
| 342 | void 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 |
| 372 | RTNET_Error_t err = RTNET_UDP_Send(...); |
| 373 | |
| 374 | switch (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) */ |
| 401 | RTNET_UDP_Send(..., RTNET_QOS_CRITICAL); |
| 402 | |
| 403 | /* Time-sensitive telemetry (< 100ms acceptable) */ |
| 404 | RTNET_UDP_Send(..., RTNET_QOS_HIGH); |
| 405 | |
| 406 | /* Bulk file transfer */ |
| 407 | RTNET_TCP_Send(...); /* Defaults to RTNET_QOS_NORMAL */ |
| 408 | |
| 409 | /* Background logging */ |
| 410 | RTNET_UDP_Send(..., RTNET_QOS_LOW); |
| 411 | ``` |
| 412 | |
| 413 | --- |
| 414 | |
| 415 | ### 5.3 Periodic Task Scheduling |
| 416 | |
| 417 | ```c |
| 418 | /* RTOS-based scheduling (recommended) */ |
| 419 | void 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 */ |
| 431 | xTaskCreate(NetworkTaskFunction, "NetTask", 512, NULL, |
| 432 | tskIDLE_PRIORITY + 2, NULL); |
| 433 | ``` |
| 434 | |
| 435 | ```c |
| 436 | /* Bare-metal scheduling */ |
| 437 | void 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 |
| 454 | void 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:** |
| 486 | 1. Verify Ethernet PHY link is up: `ETH->MACMIIAR & ETH_MACMIIAR_MB` |
| 487 | 2. Check interrupt configuration: `NVIC->ISER[ETH_IRQn >> 5]` |
| 488 | 3. Verify `RTNET_ProcessRxPacket` is called from ISR |
| 489 | 4. Check IPv6 address configuration (must be link-local or globally routable) |
| 490 | |
| 491 | ```c |
| 492 | /* Debug: Check if interrupts are firing */ |
| 493 | void 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:** |
| 509 | 1. Verify routing table has entry for destination |
| 510 | 2. Check neighbor cache has MAC address mapping |
| 511 | 3. Use Wireshark to capture packets on wire |
| 512 | 4. Verify checksums (disable HW checksum offload for debugging) |
| 513 | |
| 514 | ```c |
| 515 | /* Debug: Dump TX packets */ |
| 516 | void 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:** |
| 535 | 1. Insufficient stack size for network task |
| 536 | 2. Interrupt nesting exceeds stack limit |
| 537 | 3. Recursive calls (should never happen in this stack) |
| 538 | |
| 539 | **Solutions:** |
| 540 | ```c |
| 541 | /* Increase task stack size */ |
| 542 | xTaskCreate(NetworkTask, "Net", 1024, NULL, /* was 512 */ |
| 543 | tskIDLE_PRIORITY + 2, NULL); |
| 544 | |
| 545 | /* Reduce interrupt nesting */ |
| 546 | NVIC_SetPriority(ETH_IRQn, 6); /* Lower priority */ |
| 547 | |
| 548 | /* Monitor stack usage */ |
| 549 | UBaseType_t stackHighWaterMark = uxTaskGetStackHighWaterMark(NULL); |
| 550 | printf("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 |
| 581 | void 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 */ |
| 597 | RTNET_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 */ |
| 615 | void 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 */ |
| 647 | ETH->MACCR |= ETH_MACCR_IPCO; /* IPv4 checksum offload */ |
| 648 | |
| 649 | /* Use DMA burst mode */ |
| 650 | ETH->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 */ |
| 663 | void 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 */ |
| 672 | ETH->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 | |
| 705 | Before 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 |