FreeRTOS-Plus-TCP 配置
FreeRTOSIPConfig.h 头文件
FreeRTOS-Plus-TCP 应用程序必须提供一个 FreeRTOSIPConfig.h 头文件,
用于定义此页面上描述的参数。
配置示例
页面展示了如何为
需要最大限度减少 RAM 消耗和需要最大限度增加
吞吐量的系统设置关键配置参数。
-
影响 TCP/IP 堆栈任务执行行为的常量
-
调试、跟踪和日志记录设置
另请参阅 TCP/IP 跟踪宏。
-
硬件和驱动程序特定设置
-
TCP 相关常量
-
UDP 相关常量
-
影响套接字行为的其他常量
-
影响 ARP 行为的常量
-
影响 DHCP 和名称服务行为的常量
-
影响 IP 和 ICMP 行为的常量
-
影响 行为的常量
-
影响 行为的常量
-
提供目标支持的常量
-
向后兼容性
使用 FreeRTOS 队列将事件从应用程序任务发送到 IP
堆栈。
ipconfigEVENT_QUEUE_LENGTH
设置可以
同时排队等待处理的最大事件数。 事件队列必须至少
比网络缓冲区的总数大 5。
TCP/IP 堆栈执行自己的 RTOS 任务(尽管
任何应用程序 RTOS 任务都可以
通过已发布的套接字 API 使用其服务)。
ipconfigIP_TASK_PRIORITY
设置执行 TCP/IP 堆栈的 RTOS 任务的优先级。
优先级是
标准 FreeRTOS 任务优先级,
因此,可采用从 0(最低优先级)
到 (configMAX_PRIORITIES - 1
)(最高优先级)的任何值。 configMAX_PRIORITIES
是
在 FreeRTOSConfig.h 中定义的标准 FreeRTOS 配置参数(不是在
FreeRTOSIPConfig.h 中定义。)
对于 RTOS 任务
执行 TCP/IP 堆栈的情况,需要考虑分配给该任务的优先级相对于使用 TCP/IP 堆栈的任务的优先级。
分配给 FreeRTOS-Plus-TCP 任务的堆栈的大小,
RTOS 以字表示(而非字节数)。 FreeRTOS 包括
可选堆栈溢出检测。
如果 ipconfigPROCESS_CUSTOM_ETHERNET_FRAMES 设置为 1 ,则 TCP/IP 堆栈将调用
eApplicationProcessCustomFrameHook 处理任何未知帧,即任何需要 ARP 或 IP 的帧。
如果
ipconfigUSE_NETWORK_EVENT_HOOK
设置为 1,则 FreeRTOS-Plus-TCP
将在适当的时间调用网络事件钩子。 如果
ipconfigUSE_NETWORK_EVENT_HOOK
未设置为 1 ,则永远不会调用网络事件钩子函数。
跟踪宏
有关可用 TCP/IP 堆栈跟踪宏的信息,请参阅
另一页面。
使用 FreeRTOS 队列将事件从应用程序任务发送到 IP 堆栈。
ipconfigEVENT_QUEUE_LENGTH 设置
可同时排队等待处理的最大事件数。 如果
ipconfigCHECK_IP_QUEUE_SPACE
设置为1,则
uxGetMinimumIPQueueSpace()
函数可
用于查询自系统启动以来队列中已存在的
最小可用空间量。
UBaseType_t uxGetMinimumIPQueueSpace( void );
uxGetMinimumIPQueueSpace() 函数原型
TCP/IP 堆栈通过调用 FreeRTOS_debug_printf 宏输出
调试消息。 若要获取调试消息,请将
ipconfigHAS_DEBUG_PRINTF
设置为 1,然后
将
FreeRTOS_debug_printf()
定义为这样的函数:它接收
printf()
样式的格式字符串
和可变数量的输入,并将格式化的消息发送到
您选择的输出。
如果 ipconfigHAS_DEBUG_PRINTF
设置为 0,则不要定义 FreeRTOS_debug_printf
。
以下代码取自
用于RTOS 的 Win32 模拟器的 FreeRTOS-Plus-TCP 示例,
它能够将调试消息输出到 UDP 端口、标准输出
和到磁盘文件:
extern void vLoggingPrintf( const char *pcFormatString, ... );
#define ipconfigHAS_DEBUG_PRINTF 0
#if( ipconfigHAS_DEBUG_PRINTF == 1 )
#define FreeRTOS_debug_printf(X) vLoggingPrintf X
#endif
在 FreeRTOSIPConfig.h
中定义 ipconfigHAS_DEBUG_PRINTF 和 FreeRTOS_debug_printf
执行输出的函数(上面的代码中的 vLoggingPrintf()
)
必须是可重入函数。
一些 TCP/IP 堆栈演示应用程序生成输出消息。 TCP/IP 堆栈
通过调用 FreeRTOS_printf 宏输出这些
消息。 若要获取演示应用程序消息,请将 ipconfigHAS_PRINTF
设置为 1,然后
将 FreeRTOS_printf()
定义为这样的函数:它接收 printf()
样式的格式字符串
和可变数量的输入,并将格式化的消息发送到
您选择的输出。
如果 ipconfigHAS_PRINTF
设置为 0,则不要定义 FreeRTOS_printf
。
以下代码取自
用于RTOS 的 Win32 模拟器
的
FreeRTOS-Plus-TCP 示例,
它能够将应用程序消息输出到 UDP 端口、标准输出
和到磁盘文件:
extern void vLoggingPrintf( const char *pcFormatString, ... );
#define ipconfigHAS_PRINTF 0
#if( ipconfigHAS_PRINTF == 1 )
#define FreeRTOS_printf(X) vLoggingPrintf X
#endif
在 FreeRTOSIPConfig.h
中定义 ipconfigHAS_PRINTF 和 FreeRTOS_printf
执行输出的函数(上面的代码中的 vLoggingPrintf()
)
必须是可重入函数。
宏 configINCLUDE_TRACE_RELATED_CLI_COMMANDS
可在 FreeRTOSConfig.h 中定义。定义后,它将被分配
到 ipconfigINCLUDE_EXAMPLE_FREERTOS_PLUS_TRACE_CALLS
。它可以纳入 CLI 用于跟踪目的。
此宏的名称稍有误导性:它只检查模块 BufferAllocation_1.c 的行为。
当发现异常行为时,它会发出警告。
ipconfigTCP_MAY_LOG_PORT( x )
可以被定义为指定
FreeRTOS_lprintf()
应或不应记录哪些端口号。 例如,以下定义
将不会为端口 23 或 2402 生成日志消息:
#define ipconfigTCP_MAY_LOG_PORT(xPort) ( ( ( xPort ) != 23 ) && ( ( xPort ) != 2402 ) )
筛选日志消息
ipconfigWATCHDOG_TIMER()
是在每次遍历 IP 堆栈任务时
调用的宏,如果应用程序包含看门狗类型功能,需要知道 IP 任务
仍在循环时(虽然 IP 任务正在循环中,
这并不一定表明它正在正常运行),该宏可以起到作用。
ipconfigWATCHDOG_TIMER()
可以被定义为执行应用程序编写者期望的
任何操作。 如果未定义 ipconfigWATCHDOG_TIMER()
,则它将由预处理器
彻底移除(它将被默认为空宏)。
ipconfigHAS_ROUTING_STATISTICS
设为 1 时,能够使堆栈在 FreeRTOS_Routing.c 中统计。
它有助于记录运行时内存中的端点匹配状态。
仅用于高级驱动器实现。
当应用程序请求网络缓冲区时,虽然应用程序编写者指定了
网络缓冲区的大小,但实际获取的网络缓冲区的大小
会增加 ipconfigBUFFER_PADDING
字节。 缓冲区的
第一个字节 ipconfigBUFFER_PADDING
用于保留关于缓冲区的
元数据,以及实际存储元数据之后数据的区域。
此机制对用户是透明的,因为用户只看到指向
缓冲区内实际用于保存网络数据的区域的指针。
一些网络硬件具有非常特定的字节对齐要求,因此提供
ipconfigBUFFER_PADDING
作为可配置参数,以允许网络驱动器的
,以调整元数据之后数据
开头的对齐。
如果运行 FreeRTOS-Plus-TCP 的微控制器是大端,
ipconfigBYTE_ORDER
必须设置为 pdFREERTOS_BIG_ENDIAN
。 如果微控制器
是小 Endian,则 ipconfigBYTE_ORDER
必须设置为 pdFREERTOS_LITTLE_ENDIAN
。
“嵌入式网络基础和术语表”页面中“字节顺序和 Endian”
部分解释了
IP 网络中的字节顺序注意事项。
如果网络驱动器或网络硬件正在计算对传入数据包的校验和,
并丢弃包含无效校验和的数据包,
则将
ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM
设置为 1,
否则将
ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM
设置为 0。
通过实现利用硬件校验计算的驱动器,大大提高了
吞吐量和处理器负载。
注意:自 FreeRTOS-Plus-TCP V2.3.0 起,即便在硬件中已检查过长度,
也会在软件中对长度进行检查。
请注意:如果硬件仅支持检查 TCP 校验和,则网络接口层应
对其他协议(如 IP/UDP/ICMP/等)进行相同的处理,并将校验和验证的数据包提供给
FreeRTOS-plus-TCP 堆栈。
如果网络驱动器或网络硬件正在计算对传出数据包的 IP、TCP 和 UDP 校验,
则将
ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM
设置为
1,否则将
ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM
设置为 0。
通过实现利用硬件校验计算的驱动器,大大提高了
吞吐量和处理器负载。
以太网/硬件 MAC 地址
用于以太网帧寻址。 如果网络驱动器或硬件
正在丢弃不包含相关 MAC 地址的数据包,则将
ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES
设置为 1。 否则将
ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPES
设置为 0。
通过实现在硬件中筛选的网络地址,大大提高了
吞吐量和处理器负载。 大多数网络接口允许定义多个 MAC 地址,
以便可以通过节点的唯一硬件地址、广播地址
以及各种多播地址进行筛选。
仅适用于专家用户。
而 ipconfigETHERNET_DRIVER_FILTERS_FRAME_TYPE
用于指明
网络驱动器或硬件是否筛选以太网帧,
ipconfigETHERNET_DRIVER_FILTERS_PACKETS
用于指明
网络驱动器是否筛选以太网帧内的 IP、UDP 或 TCP 数据。
TCP/IP 堆栈仅有兴趣接收来自位于
本地节点上的套接字( IP 地址和端口号),或广播,或
多播数据包的数据。 通过阻止不符合这些标准的数据包
被发送到 TCP/IP 堆栈,大大提高了吞吐量和处理负载。
FreeRTOS 提供了一些功能,允许在网络驱动器
进行这类筛选。 例如,xPortHasUDPSocket()
可以有如下用途:
if( ( xPortHasUdpSocket( xUDPHeader->usDestinationPort ) )
#if( ipconfigUSE_DNS == 1 )
|| ( xUDPHeader->usSourcePort == FreeRTOS_ntohs( ipDNS_PORT ) )
#endif
#if( ipconfigUSE_LLMNR == 1 )
|| ( xUDPHeader->usDestinationPort == FreeRTOS_ntohs( ipLLMNR_PORT ) )
#endif
#if( ipconfigUSE_NBNS == 1 )
|| ( xUDPHeader->usDestinationPort == FreeRTOS_ntohs( ipNBNS_PORT ) )
#endif
)
{
}
else
{
}
筛选 UDP 数据包的示例
当设备连接到局域网时,强烈建议给每个传出数据包 60 字节的最小长度
(加上 4 个字节的 CRC)。宏 ipconfigETHERNET_MINIMUM_PACKET_BYTES
确定最小长度。默认情况下
它被定义为 0,这意味着数据包将按原样发送。
如果
ipconfigFILTER_OUT_NON_ETHERNET_II_FRAMES
设置为1 ,则
将丢弃不属于以太网 II 格式的以太网帧。 此选项包含在
未来潜在的 IP 堆栈开发中。
MTU 是
网络帧的有效负载可以包含的最大
字节数。 对于正常以太网 V2 帧,最大 MTU 为 1500(尽管
互联网路由可能需要更低的数字)。 设置
较低的值可以保存 RAM,这取决于所使用的缓冲区管理方案。
如果未定义 ipconfigNETWORK_MTU
,则将应用以下默认值:
#ifndef ipconfigNETWORK_MTU
#ifdef( ipconfigUSE_TCP_WIN == 1 )
#define ipconfigNETWORK_MTU ( 1526 )
#else
#define ipconfigNETWORK_MTU ( 1514 )
#endif
#endif
ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS
定义了网络缓冲区的总数量,
该缓冲区可用于 TCP/IP 堆栈。 网络缓冲区的总数是有限的,
以确保可由 TCP/IP 栈消耗的 RAM 总量限制在
预定值以内。 实际给网络缓冲区结构体分配存储区域的方式
不是固定的,而是可移植层的一部分。 最简单的
方案仅准确分配所需的存储量。
有关网络缓冲区和网络缓冲区描述符的更多信息,请参阅
描述了
将 FreeRTOS-Plus-TCP 移植到其他硬件和移植
pxGetNetworkBufferWithDescriptor()
相关 API 函数的页面。
仅限高级用户。
当 pconfigUSE_LINKED_RX_MESSAGES
设置为 1 时,可以在网络流量繁忙期间
通过将多个接收的数据包链接到一起以减少 CPU 负载,
然后一次性将所有链接的数据包传递到 IP RTOS 任务。
仅限高级用户。
如果 ipconfigZERO_COPY_RX_DRIVER
设置为 1 ,则网络接口会将网络缓冲区
NetworkBufferDescriptor_t::pucEthernetBuffer
分配到 EMAC 的 DMA。在收到数据包时不复制
任何数据。相反,缓冲区直接发送到 IP 任务。
如果禁用 TX 零拷贝选项,则每个接收的数据包都将从 DMA 缓冲区复制到
类型为 NetworkBufferDescriptor_t
的网络缓冲区。
仅限高级用户。
如果 ipconfigZERO_COPY_TX_DRIVER
设置为 1,则将始终调用
xNetworkInterfaceOutput()
驱动器函数,该函数的参数 bReleaseAfterSend
被设置为 pdTRUE
,意味着
该驱动器将始终负责释放网络缓冲区和网络
缓冲区描述符。
驱动器实现零拷贝方案很有用,数据包
数据直接从网络缓冲区内发送出去(例如通过指向在网络缓冲区内的
数据 DMA 描述符),而不是将从网络缓冲区复制数据后
再发送出去(例如通过将数据复制到
单独的预先分配的 DMA 描述符中)。 在这种情况下,驱动器需要获取
网络缓冲区的所有权,因为网络缓冲区只能
在实际传输了数据后被释放,这可能是
在 xNetworkInterfaceOutput()
函数返回之后一段时间。 请参阅
“将 FreeRTOS 移植到不同的微控制器”文档页面
的有效示例。
如果要通过 vApplicationIPNetworkEventHook_Multi () 回调接收 eNetworkDown 通知,请设置为 1。
请注意:并非所有驱动程序都支持此功能。
通常,具有错误或未知目标的 TCP 数据包将导致 RESET
被发送回远程主机。 如果
ipconfigIGNORE_UNKNOWN_PACKETS
设置为 1,
则此类重置将被抑制(不发送)。
如果
ipconfigTCP_HANG_PROTECTION
设置为 1,则 FreeRTOS-Plus-TCP 会将一个套接字
标记为关闭(如果套接字在
由
ipconfigTCP_HANG_PROTECTION_TIME
指定的一段时间内没有状态变化)。
如果
ipconfigTCP_HANG_PROTECTION
设置为 1,则
ipconfigTCP_HANG_PROTECTION_TIME
会设置
上次更改套接字状态与防挂机制将套接字标记为关闭之间
的间隔(以秒为单位)。
已连接但长时间不传输任何数据的套接字
可以由超时的路由器或防火墙断开连接。 通过确保应用程序定期发送数据包
可以避免在应用程序级出现该情况。
或者,可以将 FreeRTOS-Plus-TCP 配置为当它检测到连接处于休眠状态时,
自动发送保活消息。 请注意,尽管
有 FreeRTOS-Plus-TCP 自动发送保活消息是更方便的方法,
但这也是最不可靠的方法,因为一些路由器会丢弃保活
消息。
将 ipconfigTCP_KEEP_ALIVE
设置为 1,以使 FreeRTOS-Plus-TCP 在已连接
但处于休眠状态的套接字上定期发送保活消息。 将 ipconfigTCP_KEEP_ALIVE
设置为 0 以
防止保活消息的自动传输。
如果 FreeRTOS-Plus-TCP 未收到对保活消息的回复,则
将断开连接并将套接字标记为已关闭。 随后
在套接字上调用 FreeRTOS_recv()
将返回 -pd FREERTOS_ERRNO_ENOTCONN
。
如果
ipconfig TCP_KEEP_ALIVE
设置为 1,则
ipconfigTCP_KEEP_ALIVE_INTERVAL
会设置
连续保持消息之间的间隔(以秒为单位)。 不会发送保活消息,
除非自上次发送或接收数据包以来已过去
ipconfigTCP_KEEP_ALIVE_INTERVAL
秒
。
设置
MSS 值(以字节为单位)
用于所有 TCP 数据包。
请注意,FreeRTOS-Plus-TCP 包含的检查定义 ipconfigNETWORK_MTU
和
ipconfig TCP_MSS
有一致的值。
每个 TCP 套接字具有用于接收的缓冲区和用于传输的单独缓冲区。
默认缓冲区大小为 (4*ipconfigTCP_MSS)。
FreeRTOS_setsockopt()
可用于 FREERTOS_SO_RCVBUF
和 FREERTOS_SO_SNDBUF
参数,
以分别接收和发送缓冲区大小,但这必须
在创建套接字的时间和创建套接字所使用缓冲区的时间。
之间完成。 在实际接收数据之前不会创建接收缓冲区,
在数据实际发送到套接字进行传输之前不会创建传输缓冲区。
创建缓冲区后,无法更改其大小。
如果监听套接字
为响应传入的请求创建一个新的套接字,
则新套接字将继承监听套接字的缓冲区
大小。
定义
生存时间
TTL) 值,用于传出 TCP 数据包。
如果
ipconfigUSE_TCP_WIN
设置为 1,则每个套接字将使用一个滑动窗口。
滑动窗口允许消息乱序到达,且 FreeRTOS-Plus-TCP 使用
窗口描述符以跟踪窗口中关于所述数据包的信息。
在建立第一个 TCP 连接时分配一个描述符池。 描述符
在所有套接字之间共享。 ipconfigTCP_WIN_SEG_COUNT
设置
池中描述符的数量,每个描述符约为
64 字节。
作为示例: 如果系统将同时有最多 16 个 TCP 连接,
且每个连接将有最多 8 个段的 Rx 和 Tx 窗口,
则最坏的情况下,需要的最大描述符数为 256 (16 * 2 * 8)。
然而,实际上最坏的情况通常比上述情况要低得多,因为大多数
数据包将按顺序到达。
将
ipconfigUSE_TCP
设置为 1 以启用
TCP。
如果
ipconfigUSE_TCP
设置为 0, 则
仅
UDP 可用。
TCP 时间戳功能可用,但其用途非常有限。
时间戳只能在初始 SYN 数据包包含时间戳选项的情况下使用
。 在大多数情况下,传入连接不会设置时间戳选项。
将 ipconfigUSE_TCP_TIMESTAMPS
设置为 1 以包含 TCP 时间戳功能。
将 ipconfigUSE_TCP_TIMESTAMPS
设置为 0 以排除 TCP 时间戳功能。
滑动窗口使消息可以乱序到达。
将 ipconfigUSE_TCP_WIN
设置为 1 以将
滑动窗口行为包含
在 TCP 套接字中。将 ipconfigUSE_TCP_WIN
设置为 0,以排除 TCP 套接字中的滑动窗口行为。
滑动窗口可以增加吞吐量,同时最大限度地减少网络流量,
其代价是消耗更多 RAM。
滑动窗口可以使用
FREERTOS_SO_WIN_PROPERTIES
参数从默认大小改为 FreeRTOS_setsockopt()
。滑动窗口
大小以 MSS 为单位(因此,如果 MSS 设置为 200 字节,则
滑动窗口大小 2 等于 400 字节),并且必须始终小于
或等于两个方向上的内部缓冲区的大小。
如果监听套接字
为响应传入的请求创建一个新的套接字,
则新套接字将继承监听套接字的滑动窗口
。
TCP 平滑往返时间 (SRTT) 的最小值。
测量平滑往返时间 (SRTT) 时,结果将向上取整到最小值。默认情况下
始终为 50 ms ,但建议使用 1000 ms 的数值(请参阅 RFC6298),因为主机通常会延迟 200 ms 发送
确认数据包。
ipconfigUDP_MAX_RX_PACKETS
定义了
在 UDP 套接字的 Rx 队列中可以存在的最大数据包数量。 例如,如果
ipconfigUDP_MAX_RX_PACKETS
设置为 5,并且 UDP 套接字上已经有 5 个数据包排队,
则随后在该套接字上接收的数据包将被丢弃,直到队列长度
再次小于 5。
套接字有发送阻塞时间的属性。 如果调用了
FreeRTOS_sendto()
但
无法获取网络缓冲区,则调用 RTOS 的任务将保留在阻塞状态
(以便其他任务可以继续执行),直到网络缓冲区
变为可用或发送阻塞时间到期。 如果发送阻塞时间过期,
则发送操作中止。
允许的最大发送阻塞时间上限
是由 ipconfig UDP_MAX_SEND_BLOCK_TIME_TICKS
设置的值。 如果所有网络缓冲区都在使用中,
并且处理(并随后释放)网络缓冲区的任务本身在等待网络缓冲区时被阻塞,
设置最大允许发送阻塞时间的上限,
可防止死锁发生。
ipconfigUDP_MAX_SEND_BLOCK_TIME_TICKS
以 RTOS tick 为单位. 以毫秒为单位的
为单位的时间除以 portTICK_PERIOD_MS,
portTICK_PERIOD_MS
转换为以 tick 为单位的时间。
如果
ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS
设置为 1,则 FreeRTOS-Plus-TCP 将接受 UDP 数据包,
该数据包将校验值设置为 0,符合 UDP 规范。
如果 ipconfigUDP_PASS_ZERO_CHECKSUM_PACKETS
设置为 0 ,则 FreeRTOS-Plus-TCP 将丢弃 UDP 数据包,
该数据包将校验值设置为 0,偏离了 UDP 规范,但更安全。
注意:此配置参数默认为 0。
定义
生存时间 (TTL) 值
用于传出 UDP 数据包。
套接字的地址是其 IP 地址和端口号的
组合。
FreeRTOS_bind()
用于手动将端口号分配给套接字
(将套接字“绑定”到端口),但客户端套接字
通常不需要手动绑定(那些启动传出连接而不是
等待已知端口号上的传入连接的套接字)。 如果
ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND
设置为 1,则
在尚未绑定的套接字上调用
FreeRTOS_sendto()
将导致 IP 堆栈
自动将套接字绑定到端口号(范围:
socketAUTO_PORT_ALLOCATION_START_NUMBER
到 0xffff)。 如果
ipconfigALLOW_SOCKET_SEND_WITHOUT_BIND
设置为 0,则在尚未绑定的套接字上调用
FreeRTOS_sendto()
将导致发送操作
被中止。
实现
FreeRTOS_inet_addr()
需要使用相对较大的
字符串处理例程。 为节省代码空间,完整的
FreeRTOS_inet_addr()
实现
可自行选择,并提供了一个更小、更快的替代方案,
称为
FreeRTOS_inet_addr_quick()
。
FreeRTOS_inet_addr()
采用
点分十进制格式的 IP(例如“192.168.0.1”)作为其参数。
FreeRTOS_inet_addr_quick()
采用四个分隔开的数字组成的八进制数 IP 地址
(例如,192, 168, 0, 1)作为其参数。 如果
ipconfigINCLUDE_FULL_INET_ADDR
设置为 1,则
FreeRTOS_inet_addr()
和
FreeRTOS_indet_addr_quick()
可用。 如果
ipconfigINCLUDE_FULL_INET_ADDR
未设置为 1,则仅可用
FreeRTOS_indet_addr_quick()
。
此选项仅在套接字选择函数被激活时使用(当 ipconfigSUPPORT_SELECT_FUNCTION
为
非 0 时)。从同一任务为给定套接字调用 select()
时,不需要此宏。只有
当相同套接字上有多个任务在使用选择函数时,此选项可以防止死锁。问题是
有多个任务会等待并清除事件位 eSELECT_CALL_IP
。宏 ipconfigSELECT_USES_NOTIFY
默认为 0,表示未激活。
用于从套接字读取数据的 API 函数可以进入阻塞状态以等待数据
变成可用。
ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME
设置默认阻塞时间
以 RTOS tick 为单位。 如果未定义
ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME
,
则默认阻塞时间将设置为
portMAX_DELAY
,意味着 RTOS 任务
阻塞在读取套接字时,并且不会退出阻塞状态,直至数据可用。
请注意, 阻塞状态下的任务不会占用任何 CPU 时间。
ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME
以 tick 为单位。 宏
pdMS_TO_TICKS()
和 portTICK_PERIOD_MS
都可以用于将以毫秒为单位的时间
转换为以 tick 为单位的时间。
超时时间可以随时更改,使用 FREERTOS_SO_RCVTIMEO
参数
和 FreeRTOS_setsockopt()
。 注意: 使用无限阻塞时间
应十分谨慎,以避免出现所有任务被无限阻塞
以等待另一个 RTOS 任务(该任务也被无限阻塞)
来释放网络缓冲区的情况。
通过将发送和接收阻塞时间都设置为 0 可以将套接字设置为
非阻塞模式。 当 RTOS 任务使用多个套接字时可能需要该模式——
在这种情况下,可以通过
使用 FreeRTOS_select()
一次性在所有套接字上执行阻塞,或 RTOS 任务可以将 ipconfigSOCKET_HAS_USER_SEMAPHORE
设置为 1,
然后在自己的信号量上阻塞。
写入套接字时,写入操作可能无法立即进行。 例如,
取决于配置,写入可能需要等待网络
缓冲区变成可用。 用于将数据写入套接字的 API 函数
可进入阻塞状态等待写入成功。
ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME
设置默认阻塞时间
(以 RTOS tick 为单位)。 如果未定义
ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME
,
则默认阻塞时间将被设置为
portMAX_DELAY
,意味着 RTOS 任务
阻塞在读取套接字时,并且不会退出阻塞状态,直至数据可用。
请注意, 阻塞状态下的任务不会占用任何 CPU 时间。
ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME
以 tick 为单位。 宏
pdMS_TO_TICKS()
和 portTICK_PERIOD_MS
都可以用于将以毫秒为单位的时间
转换为以 tick 为单位的时间。
超时时间可以随时更改,使用 FREERTOS_SO_SNDTIMEO
参数
和 FreeRTOS_setsockopt()
。 注意: 使用无限阻塞时间
应十分谨慎,以避免出现所有任务被无限阻塞
以等待另一个 RTOS 任务(该任务也被无限阻塞)
来释放网络缓冲区的情况。
通过将发送和接收阻塞时间都设置为 0 可以将套接字设置为
非阻塞模式。 当 RTOS 任务使用多个套接字时可能需要该模式——
在这种情况下,可以通过
使用 FreeRTOS_select()
一次性在所有套接字上执行阻塞,或 RTOS 任务可以将 ipconfigSOCKET_HAS_USER_SEMAPHORE
设置为 1,
然后在自己的信号量上阻塞。
通过将发送和接收阻塞时间都设置为 0 可以将套接字设置为
非阻塞模式。
在默认情况下,套接字将阻塞无法立即完成的发送
或接收操作。 请参阅
ipconfigSOCK_DEFAULT_RECEIVE_BLOCK_TIME
的描述
和
ipconfigSOCK_DEFAULT_SEND_BLOCK_TIME
参数。
如果 RTOS 任务正在使用多个套接字,且在一个套接字上无法一次性进入阻塞状态,则
可以将套接字设置为非阻塞模式,并且 RTOS 任务可以在所有套接字上一次性进入阻塞状态,
通过使用 FreeRTOS_select()
函数或通过
将 ipconfigSOCKET_HAS_USER_SEMAPHORE
设置为 1,使用 FREERTOS_SO_SET_SEMAPHORE
参数
和 FreeRTOS_setsockopt()
,以向套接字提供信号量,
然后在信号量上进入阻塞状态。 当任何套接字能够进行处理时会提供信号量——
此时 RTOS 任务可以通过调用非阻塞 API 单独检查所有套接字,
确定是哪个套接字使任务
不被阻塞。
可以安装应用程序钩子,该钩子将在每个重要套接字事件后被调用。该钩子
有一个参数:socket,并且它没有返回值:
typedef void (* SocketWakeupCallback_t)( Socket_t pxSocket );
调用钩子的原因可能是以下一个或多个事件:
eSOCKET_RECEIVE = 0x0001,
eSOCKET_SEND = 0x0002,
eSOCKET_ACCEPT = 0x0004,
eSOCKET_CONNECT = 0x0008,
eSOCKET_BOUND = 0x0010,
eSOCKET_CLOSED = 0x0020,
eSOCKET_INTR = 0x0040,
通常,钩子只会通知拥有套接字的任务,以便套接字立即得到关注。
将
ipconfigSUPPORT_SELECT_FUNCTION
设置为 1,以包含对
FreeRTOS_select()
和关联 API 函数的支持,或排除
FreeRTOS_select()
和构建中的
关联 API 函数。
如果
ipconfigSUPPORT_SIGNALS
设置为 1,则
FreeRTOS_SignalSocket()
API 函数
包含在构建中。
FreeRTOS_SignalSocket()
可用于向套接字发送信号,以使任何在读取套接字时
进入阻塞状态的任务将退出阻塞状态(中止
阻塞读取操作)。
当此宏被定义为非 0 时,可以将特定的应用程序钩子(回调函数)
绑定到套接字。每个类型的事件都有不同的应用程序钩子:
FREERTOS_SO_TCP_CONN_HANDLER
FREERTOS_SO_TCP_RECV_HANDLER
FREERTOS_SO_TCP_SENT_HANDLER
FREERTOS_SO_UDP_RECV_HANDLER
FREERTOS_SO_UDP_SENT_HANDLER
ARP 缓存是一个将 IP 地址映射到 MAC 地址的表。
IP 堆栈只能向与 IP 地址关联的已知 MAC 地址或者用于联系远程 IP 地址的路由器 MAC 地址发送 UDP 消息
以移除 IP
地址。 当从远程 IP 地址接收到 UDP 消息时,
MAC 地址和 IP 地址被添加到 ARP 缓存。 当 UDP 消息
被发送到尚未出现在 ARP 缓存中的远程 IP 地址时,
UDP 消息会被请求所需 MAC 地址信息的 ARP 消息
替换掉。
ipconfigARP_CACHE_ENTRIES
定义了
可在 ARP 表中同时存在的条目的最大数量。
仅限高级用户。
在下述情况提供 ipconfigARP_STORES_REMOTE_address
:
需要从 Internet 收到回复,但要从连接到
局域网的电脑接收,而不是通过定义的网关。 在回复消息之前,
TCP/IP 堆栈 RTOS 任务将查询 ARP 表中消息的 IP 地址,但如果
ipconfigARP_STORES_REMOTE_address
设置为 0,则 ARP
将返回定义网关的 MAC 地址,因为目标地址
不在网络掩码中。 这可能妨碍答复达到其预期目的
目的地。
如果 ipconfigARP_STORES_REMOTE_address
设置为 1,则远程地址
还将存储在 ARP 表中,以及发送消息的
MAC 地址。 这可以让上述场景中的消息
正确进行路由和传送。
当分配链接层地址时,驱动器将通过发送 ARP 请求来测试该地址是否已被其他设备
使用。因此,ipconfigARP_USE_CLASH_DETECTION
必须被定义为非零。
ipconfigMAX_ARP_AGE
定义了在 ARP 表中创建或刷新条目
与由于过时而移除该条目之间的最大时间间隔。
已为接近最大存在时间的 ARP 缓存条目发送新的 ARP 请求
。
ipconfigMAX_ARP_AGE
以十秒为单位,因此 150 的值等于
1500 秒(或 25 分钟)。
未引起 ARP 响应的 ARP 请求将被重新传输,
在 ARP 请求被中止之前,重新传输次数最多为
ipconfigMAX_ARP_retransmissions
次
。
仅限高级用户。
如果 ipconfigUSE_ARP_REMOVE_ENTRY
设置为 1,则 ulARPRemoveCacheEntryByMac()
包含在构建中。 ulARPRemoveCacheEntryByMac()
使用 MAC 地址来
查找 ARP 缓存中的条目,然后将其移除。 如果 MAC 地址是
在 ARP 缓存中找到的,则返回与 MAC 地址关联的 IP 地址
。 如果在 ARP 缓存中找不到 MAC 地址,则返回 0。
uint32_t ulARPRemoveCacheEntryByMac( const MACAddress_t * pxMACAddress );
ulARPRemoveCacheEntryByMac() 函数原型
仅限高级用户。
通常 ARP 会在 MAC 地址中查找 IP 地址。 如果 ipconfigUSE_ARP_REVERSED_LOOKUP
设置为 1,则相反的函数也可用。
eARPGetCacheEntryByMac()
在 IP 地址中查找 MAC 地址。
eARPLookupResult_t eARPGetCacheEntryByMac( MACAddress_t * const pxMACAddress,
uint32_t *pulIPAddress );
eARPGetCacheEntryByMac() 函数原型
仅在使用 DHCP 时可用。如果没有 DHCP 服务器响应,请使用“自动 IP” ;设备将分配一个随机链接层
IP 地址,并测试它是否仍然可用。
通常, DHCP 服务器可以显示具有租用 IP 地址的设备的名称。
当
ipconfigDHCP_REGISTER_HOSTNAME
设置为 1 时,运行 FreeRTOS-Plus-TCP 的设备
可让一个具有人类可读名称的 DHCP 服务器来识别自己,
通过返回来自应用程序提供的名为
pcApplicationHostnameHook()
的钩子(或“回调” )函数。
当 ipconfigDHCP_REGISTER_HOSTNAME
设置为 1 时,应用程序必须提供
具有以下名称和原型的钩子(回调)函数:
const char *pcApplicationHostnameHook( void );
应用程序所提供钩子函数的名称和原型,该函数返回设备名称
查找 URL 时,可能会收到多个答案(IP地址)。此宏确定每个 URL 将存储多少个答案。
如果
ipconfigUSE_DNS_CACHE
设置为 1,则
ipconfigDNS_CACHE_ENTRIES
定义
DNS 缓存中的条目数。
DNS 主机名可以使用的最大字符数,包括 NULL
终止符。
查找主机时,库必须发送 DNS 请求并等待结果。此过程最多将重复
ipconfigDNS_REQUEST_ATTEMPTS
次。宏 ipconfigDNS_SEND_BLOCK_TIME_TICKS
确定了
函数 FreeRTOS_sendto()
可能阻塞多久。
在发送时,默认情况下,函数将阻塞最多 500 毫秒。在等待回复时,
FreeRTOS_recvfrom()
最多等待 5000 毫秒。
定义后,函数 FreeRTOS_gethostbyname_a()
变成可用。此函数将启动 DNS 查找
并设置应用程序钩子。当找到 URL 时,或当达到超时时间时,将调用
此用户函数(或钩子)。请注意,函数 FreeRTOS_gethostbyname_a()
不会使用宏
ipconfigDNS_SEND_BLOCK_TIME_TICKS
和 ipconfigDNS_RECEIVE_BLOCK_TIME_TICKS
。
当
ipconfigUSE_DHCP
设置为 1 时,DHCP 请求将在
增加的时间间隔发送,直到从 DHCP 服务器接收到任何一个响应
并且被接受,或者传输间隔达到
ipconfigMAXIMUM_DISCOVER_TX_PERIOD
。 TCP/IP 堆栈将恢复为使用
静态 IP 地址作为参数传递到
FreeRTOS_IPInit(),如果
重新传输时间间隔达到
ipconfigMAXIMUM_DISCOVER_TX_PERIOD
且没有
收到 DHCP 的答复。
如果
ipconfigUSE_DHCP
为 1,则 FreeRTOS-Plus-TCP 将尝试从 DHCP 服务器
检索 IP 地址、子网掩码、DNS 服务器地址和网关地址,并
在端点设为启用 DHCP 流而无法获取 IP 地址时恢复使用定义的静态地址。
如果 ipconfigUSE_DHCP
为 0 ,则 FreeRTOS-Plus-TCP 将不会
来自 DHCP 服务器的地址信息。相反,它将立即使用定义的静态地址
信息。
如果
ipconfigUSE_DHCPv6
为 1,则 FreeRTOS-Plus-TCP 将尝试从 DHCPv6 服务器检索
IPv6 地址、子网掩码、DNS 服务器地址和网关地址,并
在端点设为启用 DHCPv6 流而无法获取 IPv6 地址时恢复使用定义的静态地址。
如果 ipconfigUSE_DHCPv6 为 0,则 FreeRTOS-Plus-TCP 将不会尝试从 DHCPv6 服务器
获取其 IPv6 地址信息。相反,它将立即使用定义的静态地址信息。
正常
DHCP 事务
包括以下顺序:
-
客户端发送 DHCP 发现数据包以请求
来自 DHCP 服务器 IP 地址。
-
DHCP 服务器使用包含所提供的 IP 地址的提供数据包。
进行响应。
-
客户端发送 DHCP 请求数据包以领取所提供的
IP 地址。
-
DHCP 服务器发送确认数据包以授予客户端使用
所提供的 IP 地址的权限,并向客户发送
其他配置信息。 其他配置信息通常
包含
网关的 IP 地址、
DNS 的 IP 地址
以及 IP 地址租用长度。
如果 ipconfigUSE_DHCP_HOOK
设置为 1,则 FreeRTOS-Plus-TCP 将调用
应用程序提供的名为 xApplicationDHCPUserHook_Multi()
的钩子(或“回调” )函数,
该调用在初始发现数据包被发送之前和收到 DHCP 的提供之后均进行——
钩子函数可用于在 DHCP 序列中的这两个阶段中的任一个
终止 DHCP 进程。 例如,应用程序
即使当 ipconfigUSE_DHCP 设置为 1 时,写入器也可以
有效地禁用 DHCP,通过在初始发现数据包被发送之前
终止 DHCP 进程。 作为另一个示例,应用程序写入器可以检查静态 IP 地址
与网络的兼容性,设备通过接收 DHCP 服务器提供的 IP 地址
连接到该网络,但随后终止 DHCP 进程,而无需
发送请求数据包以领取所提供的 IP 地址。
如果 ipconfigUSE_DHCP_HOOK
设置为 1,则应用程序写入器必须
提供具有以下名称和原型的钩子(回调)函数:
eDHCPCallbackAnswer_t xApplicationDHCPHook_Multi( eDHCPCallbackPhase_t eDHCPPhase,
struct xNetworkEndPoint * pxEndPoint,
IP_Address_t * pxIPAddress );
DHCP 应用程序钩子函数的名称和原型
其中 eDHCPCallbackPhase_t
和 eDHCPCallbackAnswer_t
定义如下
/* Used in the DHCP callback if ipconfigUSE_DHCP_HOOK is set to 1. */
typedef enum eDHCP_PHASE
{
eDHCPPhasePreDiscover,
eDHCPPhasePreRequest
} eDHCPCallbackPhase_t;
typedef enum eDHCP_ANSWERS
{
eDHCPContinue,
eDHCPUseDefaults,
eDHCPStopNoChanges,
} eDHCPCallbackAnswer_t;
eDHCPCallbackPhase_t 和 eDHCPCallbackAnswer_t 定义
仅出于示例目的,以下是 xApplicationDHCPHook_Multi
的引用实现,
它让 DHCP 序列可以进行直到提供 IP 地址之时,
此时,比较所提供的 IP 地址与静态
配置的 IP 地址。 如果提供的和静态配置的 IP 地址是
在同一子网上,则使用静态配置的 IP 地址。 如果
提供的和静态配置的 IP 地址不在同一子网上,则
使用 DHCP 服务器提供的 IP 地址。
eDHCPCallbackAnswer_t xApplicationDHCPHook_Multi( eDHCPCallbackPhase_t eDHCPPhase,
struct xNetworkEndPoint * pxEndPoint,
IP_Address_t * pxIPAddress )
{
eDHCPCallbackAnswer_t eReturn;
uint32_t ulStaticIPAddress, ulStaticNetMask;
switch( eDHCPPhase )
{
case eDHCPPhasePreDiscover :
eReturn = eDHCPContinue;
break;
case eDHCPPhasePreRequest :
ulStaticIPAddress = FreeRTOS_inet_addr_quick( configIP_ADDR0,
configIP_ADDR1,
configIP_ADDR2,
configIP_ADDR3 );
ulStaticNetMask = FreeRTOS_inet_addr_quick( configNET_MASK0,
configNET_MASK1,
configNET_MASK2,
configNET_MASK3 );
ulStaticIPAddress &= ulStaticNetMask;
ulIPAddress &= ulStaticNetMask;
if( ulStaticIPAddress == ulIPAddress )
{
eReturn = eDHCPUseDefaults;
}
else
{
eReturn = eDHCPContinue;
}
break;
default :
eReturn = eDHCPContinue;
break;
}
return eReturn;
}
xApplicationDHCPHook() 的引用实现
当 eDHCPPhase
参数设置为 eDHCPPhasePreDiscover
时,
ulIPAddress 参数设置为正在使用的 IP 地址。 当
eDHCPPhase
参数设置为 eDHCPPhasePreRequest
,ulIPAddress
参数设置为
由 DHCP 服务器提供的 IP 地址。
将
ipconfigUSE_DNS
设置为 1 以包含基本的 DNS 客户端/解析器。 使用 DNS
通过
FreeRTOS_gethostbyname() API 函数进行。
如果
ipconfigUSE_DNS_CACHE
设置为 1,则启用 DNS 缓存。 如果
ipconfigUSE_DNS_CACHE
设置为 0,则 DNS 缓存将被禁用。
将
ipconfigUSE_LLMNR
设置为 1 以包含
LLMNR。
将
ipconfigUSE_NBNS
设置为 1 以包含
NBNS。
将
ipconfigUSE_MDNS
设置为 1,以纳入
多播 DNS。
此宏与 IPv4 有关。FreeRTOS-Plus-TCP 堆栈设为 1 时支持处理 IPv4 数据包(包括处理 IPv4 标头、ARP、DHCP 等等)。
否则,堆栈将丢弃 RX 端的所有 IPv4 数据包,并且无法传输任何 IPv4 数据包。
此宏与 IPv6 有关。FreeRTOS-Plus-TCP 堆栈设为 1 时支持处理 IPv6 数据包(包括处理 IPv6 标头、ND、RA 等等)。
否则,堆栈将丢弃 RX 端的所有 IPv6 数据包,并且无法传输任何 IPv6 数据包。
此宏与 IP 碎片化有关。通过互联网发送 IP 数据包时,大数据包可能被拆分为
较小的部件,然后由接收器组合。发件人可以确定是否允许进行这种碎片化。
默认情况下,ipconfigFORCE_IP_DONT_FRAGMENT
为 0,这意味着允许进行碎片化。
请注意,FreeRTOS-Plus-TCP 堆栈不接受收到的碎片数据包。
在回复 ICMP 数据包时,TTL 字段将被设置为此宏的值。默认值为 64
(根据 RFC 1700 的建议)。最小值为 1,最大值为 255。
如果
ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS
设置为 1,则 FreeRTOS-Plus-TCP 会接受包含 IP 选项的
IP 数据包,但不处理选项(不支持 IP 选项)。
如果 ipconfigIP_PASS_PACKETS_WITH_IP_OPTIONS
设置为 0,则 FreeRTOS-Plus-TCP 将丢弃包含 IP 选项的
IP 数据包。
如果
ipconfigREPLY_TO_INCOMMING_PINGS
设置为 1,则 TCP/IP 堆栈将
生成对传入 ICMP 回显 (ping) 请求的响应。
如果
ipconfigSUPPORT_OUTGOING_PINGS
设置为 1,则
FreeRTOS_SendPingRequest()
API 函数可用。
影响 ND 行为的常量
ND 缓存是一个将 IP 地址映射到 MAC 地址的表格。
IP 堆栈只有在知道 IPv6 地址相关的 MAC 地址或者知道用于联络远程 IPv6 地址的路由器的 MCA 地址时,才会向远程 IPv6 地址发送 TCP/UDP 消息
。当从远程 IPv6 地址收到消息时,
MAC 地址和 IPv6 地址会被添加到 ND 缓存。当 TCP/UDP 消息被发送到
尚未出现在 ND 缓存中远程 IPv6 地址时,TCP/UDP 消息会被请求
必要 MAC 地址信息的邻居请求所取代。
ipconfigND_CACHE_ENTRIES
定义了任何时刻 ND 表中可能存在的最大条目数。
影响 RA 行为的常量
如果
ipconfigUSE_RA
为 1,则 FreeRTOS-Plus-TCP 将尝试通过 SLAAC 流从 IPv6 路由器
检索 IPv6 地址、前缀地址和网关地址,并在端点设为启用 RA 流而无法获取 IPv6 地址时
恢复使用定义的静态地址。
如果 ipconfigUSE_RA
为 0,则 FreeRTOS-Plus-TCP 将不会尝试从 DHCP 服务器获取其地址信息。
相反,它将立即使用定义的静态地址信息。
RA 或路由器通告/SLAAC:请参阅端点标志 ‘bWantRA’。路由器请求将被发送。它将等待
ipconfigRA_SEARCH_TIME_OUT_MSEC
ms。当无应答时,它将重复
ipconfigRA_SEARCH_COUNT
次。然后它将检查所选的 IP 地址是否已经存在,并重复
此操作
ipconfigRA_IP_TEST_COUNT
次,每次的超时为
ipconfigRA_IP_TEST_TIME_OUT_MSEC
ms。最后,端点将进入 UP 状态。
如果正在使用的编译器支持内联函数,并且
portINLINE
被定义为
编译器的正确内联关键字,则将
ipconfigHAS_INLINE_FUNCTIONS
设置
为 1。 否则,将
IPCONFIGHAS_INLINE_FUNCTIONS
设置为 0,这将产生
使用替代宏实现的一些内联函数。
TCP/IP 堆栈调用
ipconfigRAND32()
以生成一个随机号码,
然后用作 DHCP 事务号。 随机数生成
通过此宏执行,以使应用程序可以使用自己的随机数生成
方法。 例如,可能可以通过以下方式生成随机数:
在模拟输入上采样噪声。
注意:
在 TCP/IP 堆栈启动之前,必须接种随机数生成器,
也就是说,在 之前
调用 FreeRTOS_IPInit()。
在使用可安装应用程序钩子的情况下,调用此宏以检查给定地址是否引用
有效(指令)内存。以下是一个小例子,取自 FreeRTOS_TCP _IP.c:
if( ipconfigIS_VALID_PROG_ADDRESS( pxSocket->u.xTCP.pxHandleSent ) )
{
pxSocket->u.xTCP.pxHandleSent( pxSocket, ulCount );
}
对于某些用例,用户设置发出警告消息的配置。此配置用于抑制
可移植层中的警告,使编译保持干净。
向后兼容性
如果
ipconfigCOMPATIBLE_WITH_SINGLE
设置为 1,则 FreeRTOS-Plus-TCP 假设程序中没有多个端点/接口
。一些路由函数可以简化为直接返回第一个端点/接口。
如果 ipconfigCOMPATIBLE_WITH_SINGLE
设置为 0,即默认值,则 FreeRTOS-Plus-TCP 假设程序中
允许端点/接口。
如果
ipconfigIPv4_BACKWARD_COMPATIBLE
设置为 1,则 FreeRTOS-Plus-TCP 支持 V4.0.0 之前的原始功能,
并且堆栈无法支持 IPv6。所有函数原型都会重置为原始原型。
如果 ipconfigIPv4_BACKWARD_COMPATIBLE
设置为 0,即默认值,则 FreeRTOS-Plus-TCP 将应用
V4.0.0 引入的所有新功能。
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.