Data Direction
The interrupt driven zero copy transfer mode can be used with FreeRTOS_write().
Description
ioconfigUSE_ZERO_COPY_TX must be set to 1 in
FreeRTOSIOConfig.h
for the zero copy transfer mode to be available. It
must also be explicitly enabled for the peripheral being used within the
same configuration file.
When the zero copy transfer mode is selected, FreeRTOS_write() does
not write bytes directly to the peripheral. Instead the total number
of bytes to write and a pointer to the first byte are stored inside the
FreeRTOS-Plus-IO driver. The peripheral's interrupt
service routine then uses these values to perform the actual write operation.
Bytes are copied directly from the supplied buffer to the peripheral's
registers, without being stored in any intermediary queue or buffer.
The FreeRTOS-Plus-IO driver creates and manages a mutex to ensure only
one task can perform a zero copy write at a time. The mutex must
be obtained before a task can start a zero copy write. The mutex is
obtained using a FreeRTOS_ioctl()
call with the ioctlOBTAIN_WRITE_MUTEX
request code. The FreeRTOS_ioctl() return value must
be checked to see if the mutex was obtained successfully before calling
FreeRTOS_write(). Calls to FreeRTOS_write() will fail if they are made
by a task that is not the mutex holder.
Zero copy writes are performed by the FreeRTOS-Plus-IO interrupt service routine.
It is likely that the interrupt service routine will continue to access the buffer
being written for a period of time after the call to FreeRTOS_write() that started the write operation has returned.
The buffer must not be reused or in any way corrupted until the interrupt
service routine has completed the write operation.
The FreeRTOS_ioctl()
ioctlOBTAIN_WRITE_MUTEX
and ioctlWAIT_PREVIOUS_WRITE_COMPLETE
request codes can be used for this purpose.
A task that holds the mutex, but does not perform a FreeRTOS_write(), must
manually release the mutex by calling FreeRTOS_ioctl() with the request code
set to ioctlRELEASE_WRITE_MUTEX.
The interrupt service routine and write mutex are
implemented by the FreeRTOS-Plus-IO code, and do not need to be provided by
the application writer.
Interrupt Driven Zero Copy Transfer Mode
|
Advantages
|
Disadvantages
|
-
Automatically places the calling task into the
Blocked state to wait for the write mutex to
become available. This
ensures the task calling FreeRTOS_write()
only uses CPU time when it actually has access to
the peripheral.
-
Calls to FreeRTOS_write() return immediately, allowing
the calling task to perform other operations while
the transmission is in progress.
-
Bytes are moved directly from the buffer supplied as a parameter in the
FreeRTOS_write() call to the peripheral registers by the interrupt service routine.
No additional RAM is required, and no additional copying of data
is required, making this a very efficient write
method.
-
The use of the write mutex means mutual exclusion is
built into the FreeRTOS-Plus-IO driver.
|
-
More complex usage model.
|
The ioctlUSE_ZERO_COPY_TX request code is used in a call to FreeRTOS_ioctl()
to configure a peripheral
to use the interrupt driven zero copy transfer mode for writes.
Note this request code will result in the peripheral's
interrupt being enabled, and the peripheral's interrupt priority being set to the
lowest possible. The ioctlSET_INTERRUPT_PRIORITY request code can be used
to raise the peripheral's priority if necessary.
Example Usage
Examples are also provided on the
FreeRTOS_write() API function documentation page.
#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.