|
| 1 | +# wolfIP FreeRTOS Port |
| 2 | + |
| 3 | +This directory provides a FreeRTOS integration layer for wolfIP with: |
| 4 | + |
| 5 | +- A dedicated polling task that runs `wolfIP_poll()` in a loop. |
| 6 | +- POSIX-style blocking socket calls (`socket`, `bind`, `listen`, `accept`, `recv`, `send`, `close`, ...). |
| 7 | +- Event-driven wakeups from wolfIP callbacks, synchronized with FreeRTOS mutexes/semaphores. |
| 8 | + |
| 9 | +## Files |
| 10 | + |
| 11 | +- `bsd_socket.c` |
| 12 | + FreeRTOS socket wrapper implementation and poll task. |
| 13 | +- `bsd_socket.h` |
| 14 | + Public API for initialization and socket calls. |
| 15 | + |
| 16 | +## Design |
| 17 | + |
| 18 | +1. A global lock protects wolfIP core/socket operations. |
| 19 | +2. A poll thread/task calls `wolfIP_poll()` periodically. |
| 20 | +3. Blocking socket operations: |
| 21 | + - Try the underlying non-blocking wolfIP socket call. |
| 22 | + - If `-WOLFIP_EAGAIN`, register a callback and block on a FreeRTOS semaphore. |
| 23 | + - Wake when the required event is observed, then retry. |
| 24 | + |
| 25 | +This gives application code standard blocking socket behavior while wolfIP remains polled internally. |
| 26 | + |
| 27 | +## Poll Task Example |
| 28 | + |
| 29 | +The integration creates a dedicated task similar to: |
| 30 | + |
| 31 | +```c |
| 32 | +static void wolfip_poll_task(void *arg) |
| 33 | +{ |
| 34 | + struct wolfIP *ipstack = (struct wolfIP *)arg; |
| 35 | + |
| 36 | + for (;;) { |
| 37 | + uint32_t next_ms; |
| 38 | + TickType_t delay_ticks; |
| 39 | + uint64_t now_ms = (uint64_t)xTaskGetTickCount() * (uint64_t)portTICK_PERIOD_MS; |
| 40 | + |
| 41 | + xSemaphoreTake(g_lock, portMAX_DELAY); |
| 42 | + next_ms = (uint32_t)wolfIP_poll(ipstack, now_ms); |
| 43 | + xSemaphoreGive(g_lock); |
| 44 | + |
| 45 | + if (next_ms < WOLFIP_FREERTOS_POLL_MIN_MS) { |
| 46 | + next_ms = WOLFIP_FREERTOS_POLL_MIN_MS; |
| 47 | + } |
| 48 | + if (next_ms > WOLFIP_FREERTOS_POLL_MAX_MS) { |
| 49 | + next_ms = WOLFIP_FREERTOS_POLL_MAX_MS; |
| 50 | + } |
| 51 | + |
| 52 | + delay_ticks = pdMS_TO_TICKS(next_ms); |
| 53 | + if (delay_ticks == 0) { |
| 54 | + delay_ticks = 1; |
| 55 | + } |
| 56 | + vTaskDelay(delay_ticks); |
| 57 | + } |
| 58 | +} |
| 59 | +``` |
| 60 | +
|
| 61 | +## Integration Steps |
| 62 | +
|
| 63 | +1. Include headers: |
| 64 | +
|
| 65 | +```c |
| 66 | +#include "wolfip.h" |
| 67 | +#include "bsd_socket.h" |
| 68 | +``` |
| 69 | + |
| 70 | +2. Initialize wolfIP core and low-level device first (your Ethernet/driver setup). |
| 71 | +3. Start the FreeRTOS socket layer: |
| 72 | + |
| 73 | +```c |
| 74 | +int ret = wolfip_freertos_socket_init(ipstack, poll_task_priority, poll_task_stack_words); |
| 75 | +``` |
| 76 | + |
| 77 | +4. Use POSIX-style socket API: |
| 78 | + |
| 79 | +```c |
| 80 | +int fd = socket(AF_INET, SOCK_STREAM, 0); |
| 81 | +bind(fd, ...); |
| 82 | +listen(fd, ...); |
| 83 | +int cfd = accept(fd, NULL, NULL); |
| 84 | +int n = recv(cfd, buf, sizeof(buf), 0); |
| 85 | +send(cfd, buf, n, 0); |
| 86 | +close(cfd); |
| 87 | +close(fd); |
| 88 | +``` |
| 89 | +
|
| 90 | +## API |
| 91 | +
|
| 92 | +- `int wolfip_freertos_socket_init(struct wolfIP *ipstack, UBaseType_t poll_task_priority, uint16_t poll_task_stack_words);` |
| 93 | +- `int socket_last_error(void);` |
| 94 | +- Socket calls: |
| 95 | + - `socket`, `bind`, `listen`, `accept`, `connect`, `close` |
| 96 | + - `send`, `sendto`, `recv`, `recvfrom` |
| 97 | + - `setsockopt`, `getsockopt`, `getsockname`, `getpeername` |
| 98 | +
|
| 99 | +## Configuration Knobs |
| 100 | +
|
| 101 | +Defined in `bsd_socket.c`: |
| 102 | +
|
| 103 | +- `WOLFIP_FREERTOS_BSD_MAX_FDS` (default: `16`) |
| 104 | +- `WOLFIP_FREERTOS_POLL_MIN_MS` (default: `5`) |
| 105 | +- `WOLFIP_FREERTOS_POLL_MAX_MS` (default: `20`) |
| 106 | +
|
| 107 | +Override via compiler flags, for example: |
| 108 | +
|
| 109 | +```make |
| 110 | +CFLAGS += -DWOLFIP_FREERTOS_BSD_MAX_FDS=32 |
| 111 | +``` |
| 112 | + |
| 113 | +## Notes |
| 114 | + |
| 115 | +- `wolfip_freertos_socket_init()` should be called once after wolfIP/device init and before socket usage. |
| 116 | +- File descriptors returned by this layer are wrapper FDs, not raw wolfIP internal FDs. |
| 117 | +- The wrapper is intended for task context (not ISR context). |
0 commit comments