AVED Programming Control (APC) Proxy Driver¶
Overview¶
The APC proxy driver binds in the FAL provided in initialization. Internally, it also creates a number of resources including two mutexes for protection, a mailbox to handle asynchronous responses, and a task to handle the interaction with the FAL.
The APC task will:
Pend to its mailbox, and handle the incoming messages.
Download new images to flash and update metadata.
Copy images from one partition to another.
Select partition to boot from next.
The API consists of a number of functions to download/copy an image to a location in flash memory, select boot partition and receive Flash Partition Table (FPT) data. The flash APIs will post an internal message with the required data onto the mailbox. The APC proxy task will service this mailbox and make the appropriate calls to the FAL to download/copy an image or select a new boot partition.
The API also provides two debug functions to display and clear of the stat/error counters.
Enums¶
APC proxy driver event IDs.
APC_PROXY_DRIVER_EVENTS
/**
* @enum APC_PROXY_DRIVER_EVENTS
* @brief Events raised by this proxy driver
*/
typedef enum APC_PROXY_DRIVER_EVENTS
{
APC_PROXY_DRIVER_E_DOWNLOAD_STARTED = 0,
APC_PROXY_DRIVER_E_DOWNLOAD_COMPLETE,
APC_PROXY_DRIVER_E_DOWNLOAD_BUSY,
APC_PROXY_DRIVER_E_DOWNLOAD_FAILED,
APC_PROXY_DRIVER_E_FPT_UPDATE,
APC_PROXY_DRIVER_E_COPY_STARTED,
APC_PROXY_DRIVER_E_COPY_COMPLETE,
APC_PROXY_DRIVER_E_COPY_BUSY,
APC_PROXY_DRIVER_E_COPY_FAILED,
APC_PROXY_DRIVER_E_PARTITION_SELECTED,
APC_PROXY_DRIVER_E_PARTITION_SELECTION_FAILED,
MAX_APC_PROXY_DRIVER_EVENTS
} APC_PROXY_DRIVER_EVENTS;
Boot device IDs.
APC_BOOT_DEVICES
/**
* @enum APC_BOOT_DEVICES
* @brief Enumeration of boot devices available
*/
typedef enum
{
APC_BOOT_DEVICE_PRIMARY = 0,
APC_BOOT_DEVICE_SECONDARY,
MAX_APC_BOOT_DEVICES
} APC_BOOT_DEVICES;
Structs¶
Device FPT headers.
APC_PROXY_DRIVER_FPT_HEADER
/**
* @struct APC_PROXY_DRIVER_FPT_HEADER
* @brief Structure to hold the FPT Header
*/
typedef struct APC_PROXY_DRIVER_FPT_HEADER
{
uint32_t ulMagicNum;
uint8_t ucFptVersion;
uint8_t ucFptHeaderSize;
uint8_t ucEntrySize;
uint8_t ucNumEntries;
} APC_PROXY_DRIVER_FPT_HEADER;
Device FPT partitions.
APC_PROXY_DRIVER_FPT_PARTITION
/**
* @struct APC_PROXY_DRIVER_FPT_PARTITION
* @brief Structure to hold a single FPT partition
*/
typedef struct APC_PROXY_DRIVER_FPT_PARTITION
{
uint32_t ulPartitionType;
uint32_t ulPartitionBaseAddr;
uint32_t ulPartitionSize;
} APC_PROXY_DRIVER_FPT_PARTITION;
API¶
Initialise the APC proxy driver¶
This will open the FAL using the provided handle and make use of the OSAL to create two mutexes, a mailbox, and the proxy task.
iAPC_Initialise
/**
* @brief Main initialisation point for the APC Proxy Driver
*
* @param ucProxyId Unique ID for this Proxy driver
* @param pxPrimaryFwIf Handle to the primary Firmware Interface to use
* @param pxSecondaryFwIf Handle to the secondary Firmware Interface to use
* @param ulTaskPrio Priority of the Proxy driver task (if RR disabled)
* @param ulTaskStack Stack size of the Proxy driver task
*
* @return OK Proxy driver initialised correctly
* ERROR Proxy driver not initialised, or was already initialised
*
* @note A Primary Firmware Interface handle must be passed to iAPC_Initialise,
* the secondary Firmware Interface handle however is optional
* and can be set to NULL.
*
*/
int iAPC_Initialise( uint8_t ucProxyId, FW_IF_CFG *pxPrimaryFwIf, FW_IF_CFG *pxSecondaryFwIf, uint32_t ulTaskPrio, uint32_t ulTaskStack );
Bind Callbacks¶
This API can be used to bind into a callback to be notified of events generated by the APC proxy using the EVL library. The current supported events are:
APC_PROXY_DRIVER_E_DOWNLOAD_STARTED
APC_PROXY_DRIVER_E_DOWNLOAD_COMPLETE
APC_PROXY_DRIVER_E_DOWNLOAD_BUSY
APC_PROXY_DRIVER_E_DOWNLOAD_FAILED
APC_PROXY_DRIVER_E_COPY_STARTED
APC_PROXY_DRIVER_E_COPY_COMPLETE
APC_PROXY_DRIVER_E_COPY_BUSY
APC_PROXY_DRIVER_E_COPY_FAILED
APC_PROXY_DRIVER_E_PARTITION_SELECTED
APC_PROXY_DRIVER_E_PARTITION_SELECTION_FAILED
iAPC_BindCallback
/**
* @brief Bind into this proxy driver
*
* @param pxCallback Callback to bind into the proxy driver
*
* @return OK Callback successfully bound
* ERROR Callback not bound
*
*/
int iAPC_BindCallback( EVL_CALLBACK *pxCallback );
Download Image¶
This will post a message (APC_MSG_TYPE_DOWNLOAD_PDI) onto the APC mailbox to be handled within the internal APC task to download an image to a location in NV memory.
iAPC_DownloadImage
/**
* @brief Download an image to a location in NV memory
*
* @param pxSignal Current event occurance (used for tracking)
* @param xBootDevice Target boot device
* @param iPartition The partition in the FPT to store this image in
* @param ulSrcAddr Address (in RAM) to read the image from
* @param ulImageSize Size of image (in bytes)
* @param usPacketNum Image packet number
* @param usPacketSize Size of image packet (in KB)
*
* @return OK Image downloaded successfully
* ERROR Image not downloaded successfully
*
*/
int iAPC_DownloadImage( EVL_SIGNAL *pxSignal, APC_BOOT_DEVICES xBootDevice, int iPartition, uint32_t ulSrcAddr,
uint32_t ulImageSize, uint16_t usPacketNum, uint16_t usPacketSize );
Update FPT¶
This will post a message (APC_MSG_TYPE_DOWNLOAD_PDI) onto the APC mailbox to be handled within the internal APC task to download an image to a location in NV memory and update the FPT.
iAPC_UpdateFpt
/**
* @brief Download an image with an FPT to a location in NV memory
*
* @param pxSignal Current event occurance (used for tracking)
* @param xBootDevice Target boot device
* @param ulSrcAddr Address (in RAM) to read the image from
* @param ulImageSize Size of image (in bytes)
* @param usPacketNum Image packet number
* @param usPacketSize Size of image packet (in KB)
* @param iLastPacket Boolean indicating if this is the last data packet
*
* @return OK Image downloaded successfully
* ERROR Image not downloaded successfully
*
*/
int iAPC_UpdateFpt( EVL_SIGNAL *pxSignal, APC_BOOT_DEVICES xBootDevice, uint32_t ulSrcAddr, uint32_t ulImageSize,
uint16_t usPacketNum, uint16_t usPacketSize, int iLastPacket );
Copy Image¶
This will post a message (APC_MSG_TYPE_COPY_PDI) onto the APC mailbox to be handled within the internal APC task to copy an image from one partition to another.
iAPC_CopyImage
/**
* @brief Copy an image from one partition to another
*
* @param pxSignal Current event occurance (used for tracking)
* @param xSrcBootDevice Target boot device to copy from
* @param iSrcPartition The partition in the FPT to copy this image from
* @param xDestBootDevice Target boot device to copy to
* @param iDestPartition The partition in the FPT to copy this image to
* @param ulCpyAddr Address (in RAM) to copy the source partition to before writing it
* @param ulAllocatedSize Maximum size available to copy
*
* @return OK Image copied successfully
* ERROR Image not copied successfully
*
*/
int iAPC_CopyImage( EVL_SIGNAL *pxSignal, APC_BOOT_DEVICES xSrcBootDevice, int iSrcPartition,
APC_BOOT_DEVICES xDestBootDevice, int iDestPartition, uint32_t ulCpyAddr, uint32_t ulAllocatedSize );
Set Next Partition¶
This will post a message (APC_MSG_TYPE_PARTITION_SELECT) onto the APC mailbox to be handled within the internal APC task to select which partition to boot from.
iAPC_SetNextPartition
/**
* @brief Select which partition to boot from
*
* @param pxSignal Current event occurance (used for tracking)
* @param iPartition The partition to boot from on the next reset
*
* @return OK Partition successfully selected
* ERROR Partition not selected
*/
int iAPC_SetNextPartition( EVL_SIGNAL *pxSignal, int iPartition );
Enable Hot Reset¶
This will post a message (APC_MSG_TYPE_ENABLE_HOT_RESET) onto the APC mailbox to be handled within the internal APC task to enable the hot reset capability.
iAPC_EnableHotReset
/**
* @brief Enable the hot reset capability
*
* @param pxSignal Current event occurance (used for tracking)
*
* @return OK Hot reset successfully enabled
* ERROR Hot reset not enabled
*/
int iAPC_EnableHotReset( EVL_SIGNAL *pxSignal );
Get FPT Header¶
This will copy the locally stored Flash Partition Table (FPT) header data into the passed FPT header struct. This process is mutex protected.
iAPC_GetFptHeader
/**
* @brief Get the Flash Partition Table (FPT) Header
*
* @param xBootDevice Target boot device
* @param pxFptHeader Pointer to the FPT header data
*
* @return OK FPT header retrieved successfully
* ERROR FPT header not retrieved successfully
*
*/
int iAPC_GetFptHeader( APC_BOOT_DEVICES xBootDevice, APC_PROXY_DRIVER_FPT_HEADER *pxFptHeader );
Get FPT Partition¶
This will copy the locally stored Flash Partition Table (FPT) partition data into the passed FPT partition struct. This process is mutex protected.
iAPC_GetFptPartition
/**
* @brief Get a Flash Partition Table (FPT) Partition
*
* @param xBootDevice Target boot device
* @param iPartition Index of partition to retrieve (0 is the 1st partition)
* @param pxFptPartition Pointer to the FPT partition data
*
* @return OK FPT partition retrieved successfully
* ERROR FPT partition not retrieved successfully
*
*/
int iAPC_GetFptPartition( APC_BOOT_DEVICES xBootDevice, int iPartition, APC_PROXY_DRIVER_FPT_PARTITION *pxFptPartition );
Print Statistics¶
Debug function used to display the statistic counters and errors.
iAPC_PrintStatistics
/**
* @brief Print all the stats gathered by the proxy driver
*
* @return OK Stats retrieved from proxy driver successfully
* ERROR Stats not retrieved successfully
*
*/
int iAPC_PrintStatistics( void );
Clear Statistics¶
Debug function used to clear the all statistics counters back to zero.
iAPC_ClearStatistics
/**
* @brief Clear all the stats in the proxy driver
*
* @return OK Stats cleared successfully
* ERROR Stats not cleared successfully
*
*/
int iAPC_ClearStatistics( void );
Get State¶
Gets current state of APC proxy driver
iAPC_GetState
/**
* @brief Gets the current state of the proxy driver
*
* @param pxState Pointer to the state
*
* @return OK If successful
* ERROR If not successful
*/
int iAPC_GetState( MODULE_STATE *pxState );
Sequence Diagrams¶
APC Proxy Initialization¶
Two APC API functions are called from the AMC main task (iAPC_Initialise and iAPC_BindCallback), in order to initialize the proxy.
iAPC_Initialise will call into the FAL to open with the provided handle, create two shared proxy mutexes, create a proxy mailbox and create the proxy task.
iAPC_BindCallback will bind the appropriate top-level callback function.
APC Proxy Task¶
The Task within APC has a number of responsibilities:
Pend to its mailbox, and handle the incoming messages.
Download new image to flash and update metadata.
Copy image from one partition to another.
Select partition to boot from next.
The sequence flow diagram below outline the top-level functionality of the APC proxy task. Some complexity has been hidden within local functions, namely iDownloadImage(), iCopyImage() and iSelectPartition().
Examples¶
Initialize Driver¶
This function should only be called once. It requires an unique ID for the proxy, used for signaling new events from the proxy, along with a handle to a FW_IF (already created and initialized), proxy driver task priority and stack size.
iAPC_Initialise Example
if( OK == iAPC_Initialise( AMC_EVENT_UNIQUE_ID_APC, &xPrimaryIf, &xSecondaryIf, AMC_TASK_PRIO_DEFAULT, AMC_APC_TASK_STACK ) )
{
AMC_PRINTF( "APC Proxy Driver initialised\r\n" );
}
else
{
AMC_PRINTF( "Error initialising APC Proxy Driver\r\n" );
}
Register For Callback¶
Define a function based on the function pointer prototype and bind in using the API.
iAPC_BindCallback Example
/* Define a callback to handle the events */
static int iApcCallback( EVL_SIGNAL *pxSignal )
{
int iStatus = ERROR;
if( ( NULL != pxSignal ) && ( AMC_EVENT_UNIQUE_ID_APC == pxSignal->ucModule ) )
{
switch( pxSignal->ucEventType )
{
case APC_PROXY_DRIVER_E_DOWNLOAD_STARTED:
case APC_PROXY_DRIVER_E_DOWNLOAD_COMPLETE:
case APC_PROXY_DRIVER_E_DOWNLOAD_FAILED:
case APC_PROXY_DRIVER_E_DOWNLOAD_BUSY:
case APC_PROXY_DRIVER_E_COPY_STARTED:
case APC_PROXY_DRIVER_E_COPY_COMPLETE:
case APC_PROXY_DRIVER_E_COPY_FAILED:
case APC_PROXY_DRIVER_E_COPY_BUSY:
case APC_PROXY_DRIVER_E_PARTITION_SELECTED:
case APC_PROXY_DRIVER_E_PARTITION_SELECTION_FAILED:
/* TODO: handle events */
iStatus = OK;
break;
default:
break;
}
}
return iStatus;
}
/* Bind into the callback during the application initialisation */
if( OK == iAPC_BindCallback( &iApcCallback ) )
{
AMC_PRINTF( "APC Proxy Driver initialised and bound\r\n" );
}
else
{
AMC_PRINTF( "Error binding to Proxy Driver\r\n" );
}
Download image¶
Example of downloading an image to flash.
iAPC_DownloadImage Example
int iInstance = 0; /* set to desired request instance */
int iPartition = 0; /* set to desired partition number */
int iImageSize = 0; /* set to desired image size (bytes) */
uint32_t ulSrcAddr = 0; /* set to desired source (RAM) address */
uint16_t usPacketNum = 0; /* set to desired packet number */
uint16_t usPacketSize = 0; /* set to desired packet size */
APC_BOOT_DEVICES xBootDev = APC_BOOT_DEVICE_PRIMARY;
EVL_SIGNAL xSignal = { 0 };
xSignal.ucInstance = iInstance;
if( OK != iAPC_DownloadImage( &xSignal, xBootDev, iPartition, ulSrcAddr, ( uint32_t )iImageSize, usPacketNum, usPacketSize ) )
{
APC_DBG_PRINTF( "Error writing %d bytes to partition %d\r\n", iImageSize, iPartition );
}
else
{
APC_DBG_PRINTF( "%d bytes written from 0x%08X to partition %d\r\n",
iImageSize, ulSrcAddr, iPartition );
}
Copy image¶
Example of copying an image to flash.
iAPC_CopyImage Example
int iInstance = 0; /* set to desired request instance */
int iSrcPartition = 0; /* set to desired source partition number */
int iDestPartition = 0; /* set to desired destination partition number */
int iImageSize = 0; /* set to desired image size (max num bytes) */
uint32_t ulSrcAddr = 0; /* set to desired source (RAM) address */
APC_BOOT_DEVICES xBootDev = APC_BOOT_DEVICE_PRIMARY;
EVL_SIGNAL xSignal = { 0 };
xSignal.ucInstance = iInstance;
if( OK != iAPC_CopyImage( &xSignal, xBootDev, iSrcPartition, iDestPartition, ulSrcAddr, ( uint32_t )iImageSize ) )
{
APC_DBG_PRINTF( "Error copying partition %d partition %d\r\n", iSrcPartition, iDestPartition );
}
else
{
APC_DBG_PRINTF( "Partition %d copied to partition %d\r\n",
iSrcPartition, iDestPartition );
}
Sets¶
Set next partition¶
Example of selecting the next boot partition.
iAPC_SetNextPartition Example
int iInstance = 0; /* set to desired request instance */
int iPartition = 0; /* set to desired partition number */
EVL_SIGNAL xSignal = { 0 };
xSignal.ucInstance = iInstance;
if( OK != iAPC_SetNextPartition( &xSignal, iPartition ) )
{
APC_DBG_PRINTF( "Error selecting partition %d\r\n", iPartition );
}
else
{
APC_DBG_PRINTF( "Selected partition %d\r\n", iPartition );
}
Enable hot reset¶
Example of enabling hot rest capability.
iAPC_EnableHotReset Example
int iInstance = 0; /* set to desired request instance */
EVL_SIGNAL xSignal = { 0 };
xSignal.ucInstance = iInstance;
if( OK != iAPC_EnableHotReset( &xSignal ) )
{
PLL_DAL( APC_DBG_NAME, "Error enabling hot reset\r\n" );
}
else
{
PLL_DAL( APC_DBG_NAME, "Hot reset enabled\r\n" );
}
Gets¶
Get FPT header¶
Example of retrieving the FPT header.
iAPC_GetFptHeader Example
APC_PROXY_DRIVER_FPT_HEADER xFptHeader = { 0 };
APC_BOOT_DEVICES xBootDev = APC_BOOT_DEVICE_PRIMARY;
if( OK != iAPC_GetFptHeader( xBootDev, &xFptHeader ) )
{
APC_DBG_PRINTF( "Error retrieving FPT header\r\n" );
}
else
{
APC_DBG_PRINTF( "======================================================================\r\n" );
APC_DBG_PRINTF( "FPT header:\r\n" );
APC_DBG_PRINTF( "\tMagic number . . . . . : 0x%08X\r\n", xFptHeader.ulMagicNum );
APC_DBG_PRINTF( "\tFPT version. . . . . . : 0x%02X\r\n", xFptHeader.ucFptVersion );
APC_DBG_PRINTF( "\tFPT header size. . . . : 0x%02X\r\n", xFptHeader.ucFptHeaderSize );
APC_DBG_PRINTF( "\tEntry size . . . . . . : 0x%02X\r\n", xFptHeader.ucEntrySize );
APC_DBG_PRINTF( "\tNum entries. . . . . . : 0x%02X\r\n", xFptHeader.ucNumEntries );
APC_DBG_PRINTF( "======================================================================\r\n" );
}
Get FPT partition¶
Example of retrieving an FPT partition.
iAPC_GetFptPartition Example
int iPartition = 0; /* set to desired partition number */
APC_PROXY_DRIVER_FPT_PARTITION xFptPartition = { 0 };
APC_BOOT_DEVICES xBootDev = APC_BOOT_DEVICE_PRIMARY;
if( OK != iAPC_GetFptPartition( xBootDev, iPartition, &xFptPartition ) )
{
APC_DBG_PRINTF( "Error retrieving FPT Partition %d\r\n", iPartition );
}
else
{
APC_DBG_PRINTF( "======================================================================\r\n" );
APC_DBG_PRINTF( "FPT partition %d:\r\n", iPartition );
APC_DBG_PRINTF( "\tPartition type . . . . : 0x%08X\r\n", xFptPartition.ulPartitionType );
APC_DBG_PRINTF( "\tPartition base address : 0x%08X\r\n", xFptPartition.ulPartitionBaseAddr );
APC_DBG_PRINTF( "\tPartition size . . . . : 0x%08X\r\n", xFptPartition.ulPartitionSize );
APC_DBG_PRINTF( "======================================================================\r\n" );
}
Page Revision: v. 32