数据方向
中断驱动的零拷贝传输模式可以与 FreeRTOS_write() 一起使用。
说明
ioconfigUSE_ZERO_COPY_TX 必须在
FreeRTOSIOConfig.h 中设置为 1,
以使零拷贝传输模式可用。 另外,
其必须被明确启用于 相同配置文件中使用的
相同配置文件中使用的外围设备明确启用。
当选择零拷贝传输模式时,FreeRTOS_write()
不直接将字节写入外围设备。 相反,待写入的总字节数
和指向第一个字节的指针存储于
FreeRTOS-Plus-IO 驱动器内。 随后,外围设备的中断
服务程序使用这些值来执行实际写入操作。
字节从提供的缓冲区直接被拷贝到外围设备的
寄存器,而不存储在任何中间队列或缓冲区中。
FreeRTOS-Plus-IO 驱动器可以创建和管理互斥锁,以确保同时仅有
一项任务可以执行零拷贝写入。 必须
在任务能够开始零拷贝写入之前获取互斥锁。 互斥锁
可通过调用 FreeRTOS_ioctl()
(使用 ioctlOBTAIN_WRITE_MUTEX 请求代码)
获取。 请务必检查 FreeRTOS_ioctl() 返回值,
确认是否已成功获取互斥锁,该检查步骤必须在调用
FreeRTOS_write() 前执行。 如果通过非互斥锁持有者的任务调用 FreeRTOS_write() ,调用将失败
。
零拷贝写入由 FreeRTOS-Plus-IO 中断服务程序执行。
在启动写入操作的
FreeRTOS_write() 调用返回后,中断服务程序可能会继续访问被写入的缓冲区一段时间。
直到中断服务程序完成写入操作前,不得重复使用缓冲区或以任何方式损坏缓冲区
。
FreeRTOS_ioctl()、
ioctlOBTAIN_WRITE_MUTEX
和 ioctlWAIT_PREVIOUS_WRITE_COMPLETE
请求代码可用于此用途。
一项持有互斥锁但不执行 FreeRTOS_WRITE() 的任务必须
通过使用请求代码调用 FreeRTOS_ioctl() 以手动释放互斥锁,
请求代码应设置为 ioctlRELEASE_WRITE_MUTEX。
中断服务程序和写入互斥锁
由 FreeRTOS-Plus-IO 代码提供,无需由
应用程序编写者提供。
中断驱动的零拷贝传输模式
|
优点
|
缺点
|
-
自动将调用任务置于
阻塞状态,等待写入互斥锁
变为可用。这
确保了调用 FreeRTOS_write() 的任务
仅当它确实可以访问外围设备时才使用 CPU 时间
。
-
对 FreeRTOS_write() 的调用可立即返回,允许
调用任务在传输过程中执行其他操作。
。
-
通过中断服务程序,字节直接从提供的缓冲区中作为
FreeRTOS_write() 调用中的参数被传输至外围寄存器。
无需额外的 RAM,无需额外拷贝数据,
实为一非常高效的写入
方法。
-
使用写入互斥锁表示双向互斥已被
内置于 FreeRTOS-Plus-IO 驱动器中。
|
|
ioctlUSE_ZERO_COPY_TX 请求代码用于调用 FreeRTOS_ioctl()
以配置外围设备,
使用中断驱动的零拷贝传输模式进行写入。
请注意,此请求代码将导致外围设备的
中断被启用,且外围设备的中断优先级被设置为
可能的最低值。 可以使用 ioctlSET_INTERRUPT_PRIORITY 请求代码
在必要时提高外围设备的优先级。
示例用法
FreeRTOS_write() API 函数文档页面也提供了相关示例。
#include "FreeRTOS_IO.h"
void vAFunction( void )
{
Peripheral_Descriptor_t xOpenedPort;
BaseType_t xReturned;
const uint32_t ulMaxBlock100ms = ( 100UL / portTICK_PERIOD_MS );
xOpenedPort = FreeRTOS_open( "/SPI2/", NULL );
if( xOpenedPort != NULL )
{
FreeRTOS_ioctl( xOpenedPort, ioctlUSE_ZERO_COPY_TX, NULL );
xReturned = FreeRTOS_ioctl( xOpenedPort, ioctlOBTAIN_WRITE_MUTEX, ulMaxBlock100ms );
if( xReturned == pdTRUE )
{
xReturned = FreeRTOS_write( xOpenedPort, ucBuffer, 100 );
if( xReturned == 100 )
{
}
}
xReturned = FreeRTOS_ioctl( xOpenedPort, ioctlOBTAIN_WRITE_MUTEX, ulMaxBlock100ms );
if( xReturned == pdTRUE )
{
memset( ucBuffer, 0, 100 );
xReturned = FreeRTOS_write( xOpenedPort, ucBuffer, 100 );
}
FreeRTOS_ioctl( xOpenedPort, ioctlWAIT_PREVIOUS_WRITE_COMPLETE, ulMaxBlock100ms );
}
}
Copyright (C) Amazon Web Services, Inc. or its affiliates. All rights reserved.