512 lines
17 KiB
C
512 lines
17 KiB
C
/**
|
|
*
|
|
* \file
|
|
*
|
|
* \brief WINC3400 Flash Interface.
|
|
*
|
|
* Copyright (c) 2017-2018 Microchip Technology Inc. and its subsidiaries.
|
|
*
|
|
* \asf_license_start
|
|
*
|
|
* \page License
|
|
*
|
|
* Subject to your compliance with these terms, you may use Microchip
|
|
* software and any derivatives exclusively with Microchip products.
|
|
* It is your responsibility to comply with third party license terms applicable
|
|
* to your use of third party software (including open source software) that
|
|
* may accompany Microchip software.
|
|
*
|
|
* THIS SOFTWARE IS SUPPLIED BY MICROCHIP "AS IS". NO WARRANTIES,
|
|
* WHETHER EXPRESS, IMPLIED OR STATUTORY, APPLY TO THIS SOFTWARE,
|
|
* INCLUDING ANY IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY,
|
|
* AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT WILL MICROCHIP BE
|
|
* LIABLE FOR ANY INDIRECT, SPECIAL, PUNITIVE, INCIDENTAL OR CONSEQUENTIAL
|
|
* LOSS, DAMAGE, COST OR EXPENSE OF ANY KIND WHATSOEVER RELATED TO THE
|
|
* SOFTWARE, HOWEVER CAUSED, EVEN IF MICROCHIP HAS BEEN ADVISED OF THE
|
|
* POSSIBILITY OR THE DAMAGES ARE FORESEEABLE. TO THE FULLEST EXTENT
|
|
* ALLOWED BY LAW, MICROCHIP'S TOTAL LIABILITY ON ALL CLAIMS IN ANY WAY
|
|
* RELATED TO THIS SOFTWARE WILL NOT EXCEED THE AMOUNT OF FEES, IF ANY,
|
|
* THAT YOU HAVE PAID DIRECTLY TO MICROCHIP FOR THIS SOFTWARE.
|
|
*
|
|
* \asf_license_stop
|
|
*
|
|
*/
|
|
|
|
/**@defgroup FLASHAPI FLASH
|
|
*/
|
|
|
|
#ifndef __M2M_FLASH_H__
|
|
#define __M2M_FLASH_H__
|
|
|
|
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
|
|
INCLUDES
|
|
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
|
|
#include "common/include/nm_common.h"
|
|
#include "driver/include/m2m_types.h"
|
|
|
|
/**@defgroup FlashDefs Defines
|
|
* @ingroup FLASHAPI
|
|
* @{*/
|
|
|
|
|
|
/*! Bit 0 of u8Options parameter of @ref m2m_flash_updateimage.\n
|
|
* Request to write new firmware image to WINC inactive partition. */
|
|
#define FLASH_UPDATEIMAGE_OPTION_UPDATE NBIT0
|
|
/*! Bit 1 of u8Options parameter of @ref m2m_flash_updateimage.\n
|
|
* Request to mark image in WINC inactive partition as valid. If set along with
|
|
* @ref FLASH_UPDATEIMAGE_OPTION_UPDATE, the image is not marked valid if the writing fails. */
|
|
#define FLASH_UPDATEIMAGE_OPTION_VALIDATE NBIT1
|
|
/*! Bit 2 of u8Options parameter of @ref m2m_flash_updateimage.\n
|
|
* Request to switch the WINC active/inactive partitions. Use this to switch to a new image or to
|
|
* revert to an old one. The switch only succeeds if the image has been marked valid. */
|
|
#define FLASH_UPDATEIMAGE_OPTION_SWITCH NBIT2
|
|
|
|
/*! Return success, transfer succeeded. */
|
|
#define FLASH_SUCCESS 0
|
|
/*! Return error. The parameters provided by the MCU application failed sanity checks. */
|
|
#define FLASH_ERR_PARAM (-1)
|
|
/*! Return error. An MCU application function of type @ref tpfDataAccessFn returned failure. */
|
|
#define FLASH_ERR_LOCAL_ACCESS (-2)
|
|
/*! Return error. There was an error while accessing WINC flash, or contents of WINC flash were not as expected. */
|
|
#define FLASH_ERR_WINC_ACCESS (-3)
|
|
/*! Return error. The transfer destination location was too small for the size of data to be transferred. */
|
|
#define FLASH_ERR_SIZE (-4)
|
|
/*! Return error. The data provided by the MCU application caused a failure. For example:\n
|
|
* - An item could not be added to a WINC flash store because the identifier matched an existing item.
|
|
* - An item could not be read or removed from a WINC flash store because the identifier did not match an existing item.
|
|
* - A firmware image could not be written to WINC flash because it did not match the format of WINC firmware images. */
|
|
#define FLASH_ERR_WINC_CONFLICT (-5)
|
|
/*! Return error. The MCU application did not call @ref m2m_flash_init during Wi-Fi initialization. */
|
|
#define FLASH_ERR_UNINIT (-6)
|
|
/*! Return error. The module hit an internal error, such as insufficient heap memory. */
|
|
#define FLASH_ERR_INTERNAL (-7)
|
|
|
|
/**@}
|
|
*/
|
|
/**@defgroup FlashEnums Enumeration/Typedefs
|
|
* @ingroup FLASHAPI
|
|
* @{*/
|
|
|
|
/*!
|
|
@enum tenuFlashDataFnCtl
|
|
|
|
@brief Control parameter for @ref tpfDataAccessFn.
|
|
*/
|
|
typedef enum {
|
|
/*! Data access about to start. Check and save parameters as required, ready for subsequent
|
|
* data accesses. */
|
|
FLASH_DATA_FN_INITIALIZE,
|
|
/*! Sequential data access, using parameters previously provided by FLASH_DATA_FN_INITIALIZE. */
|
|
FLASH_DATA_FN_DATA,
|
|
/*! Data access aborted. Did not complete and will not be continued. */
|
|
FLASH_DATA_FN_TERMINATE,
|
|
/*! Data access complete. */
|
|
FLASH_DATA_FN_COMPLETE
|
|
}tenuFlashDataFnCtl;
|
|
|
|
/*!
|
|
@enum tenuDataFnRW
|
|
|
|
@brief Indicates whether data is to be read or written
|
|
*/
|
|
typedef enum {
|
|
/*! Read data from application memory. */
|
|
FLASH_DATA_FN_READ,
|
|
/*! Write data to application memory. */
|
|
FLASH_DATA_FN_WRITE
|
|
}tenuDataFnRW;
|
|
|
|
/*!
|
|
@enum tenuImageId
|
|
|
|
@brief Indicates which image to access in WINC flash
|
|
*/
|
|
typedef enum {
|
|
/*! Access the image in the inactive partition. */
|
|
FLASH_IMAGE_INACTIVE,
|
|
/*! Access the image in the active partition. */
|
|
FLASH_IMAGE_ACTIVE
|
|
}tenuImageId;
|
|
|
|
|
|
/*!
|
|
@typedef \
|
|
tpfDataAccessFn
|
|
|
|
@brief
|
|
A function of this type is used for local data access. It can be implemented to handle simple
|
|
RAM access with pointer/length, or it can be implemented to handle access to external memory.
|
|
Functions of this type are provided to the module via various function APIs.
|
|
@see m2m_flash_rootcert_add
|
|
@see m2m_flash_rootcert_read
|
|
@see m2m_flash_rootcert_readidx
|
|
@see m2m_flash_updateimage
|
|
@see m2m_flash_readimage
|
|
|
|
@param [in] enuCtl
|
|
Control parameter.
|
|
@param [in] pvStr
|
|
Generic pointer to structure. The structure type depends on enuCtl:
|
|
- @ref tstrDataAccessInitParamsApp if enuCtl is @ref FLASH_DATA_FN_INITIALIZE.
|
|
- @ref tstrDataAccessParamsApp if enuCtl is @ref FLASH_DATA_FN_DATA.
|
|
- @ref NULL if enuCtl is @ref FLASH_DATA_FN_TERMINATE or @ref FLASH_DATA_FN_COMPLETE.
|
|
|
|
@note The function is typically called by the module multiple times during a data transfer:
|
|
Once with @ref FLASH_DATA_FN_INITIALIZE, then multiple times with @ref FLASH_DATA_FN_DATA, then
|
|
once with @ref FLASH_DATA_FN_COMPLETE.
|
|
|
|
@return Zero for success. Non-zero otherwise.
|
|
|
|
\section FlashExample1 Example
|
|
This example illustrates an implementation of a function of type @ref tpfDataAccessFn. \n
|
|
This example assumes the application's data buffer is in RAM, so we can use memcpy. Alternatively
|
|
memcpy can be replaced by dedicated functions which read/write the application buffer.
|
|
|
|
gpu8DataLocation is a pointer to the data buffer in RAM, set by the application. \n
|
|
gu32DataSize is the size of the data buffer, set by the application.
|
|
|
|
@code{.c}
|
|
sint8 data_access_ptr(tenuFlashDataFnCtl enuCtl, void *pvStr)
|
|
{
|
|
// Return value.
|
|
sint8 s8Ret = -1;
|
|
// Fixed variables, set in case FLASH_DATA_FN_INITIALIZE, reset in case FLASH_DATA_FN_COMPLETE.
|
|
static tenuDataFnRW enuRW;
|
|
static uint8 *pu8Location = NULL;
|
|
static uint32 u32BytesRemaining = 0;
|
|
|
|
switch (enuCtl)
|
|
{
|
|
case FLASH_DATA_FN_INITIALIZE:
|
|
if (pvStr != NULL)
|
|
{
|
|
tstrDataAccessInitParamsApp *init_params = (tstrDataAccessInitParamsApp*)pvStr;
|
|
if (init_params->u32TotalSize > gu32DataSize)
|
|
break;
|
|
// Set fixed variables.
|
|
enuRW = init_params->enuRW;
|
|
pu8Location = gpu8DataLocation;
|
|
u32BytesRemaining = init_params->u32TotalSize;
|
|
s8Ret = 0;
|
|
}
|
|
break;
|
|
case FLASH_DATA_FN_DATA:
|
|
if ((pvStr != NULL) && (pu8Location != NULL))
|
|
{
|
|
tstrDataAccessParamsApp *params = (tstrDataAccessParamsApp*)pvStr;
|
|
// Some sanity checks which should never fail.
|
|
if (u32BytesRemaining < params->u32DataSize)
|
|
break;
|
|
if (params->pu8Data == NULL)
|
|
break;
|
|
switch (enuRW)
|
|
{
|
|
case FLASH_DATA_FN_WRITE:
|
|
memcpy(pu8Location, params->pu8Data, params->u32DataSize);
|
|
s8Ret = 0;
|
|
break;
|
|
case FLASH_DATA_FN_READ:
|
|
memcpy(params->pu8Data, pu8Location, params->u32DataSize);
|
|
s8Ret = 0;
|
|
break;
|
|
}
|
|
// Update fixed variables for sequential access.
|
|
pu8Location += params->u32DataSize;
|
|
u32BytesRemaining -= params->u32DataSize;
|
|
}
|
|
break;
|
|
case FLASH_DATA_FN_TERMINATE:
|
|
case FLASH_DATA_FN_COMPLETE:
|
|
// Reset fixed variables.
|
|
pu8Location = NULL;
|
|
u32BytesRemaining = 0;
|
|
s8Ret = 0;
|
|
break;
|
|
}
|
|
return s8Ret;
|
|
}
|
|
@endcode
|
|
*/
|
|
typedef sint8 (*tpfDataAccessFn) (tenuFlashDataFnCtl enuCtl, void *pvStr);
|
|
|
|
/*!
|
|
@struct \
|
|
tstrDataAccessInitParamsApp
|
|
@brief
|
|
This structure contains parameters for initializing a local data access (read or write).
|
|
|
|
@see tpfDataAccessFn.
|
|
*/
|
|
typedef struct {
|
|
/*! Total size of data to be accessed in data location. */
|
|
uint32 u32TotalSize;
|
|
/*! Flags indicating type of data access (read or write). */
|
|
tenuDataFnRW enuRW;
|
|
}tstrDataAccessInitParamsApp;
|
|
|
|
/*!
|
|
@struct \
|
|
tstrDataAccessParamsApp
|
|
@brief
|
|
This structure contains data for local data access (read or write).
|
|
@see tpfDataAccessFn.
|
|
*/
|
|
typedef struct {
|
|
/*! Buffer to be written from or read to. */
|
|
uint8 *pu8Data;
|
|
/*! Size of data to be written or read. */
|
|
uint32 u32DataSize;
|
|
}tstrDataAccessParamsApp;
|
|
|
|
/*!
|
|
@struct \
|
|
tstrFlashState
|
|
@brief
|
|
This structure contains information about an attempted transfer.
|
|
@see m2m_flash_init
|
|
*/
|
|
typedef struct {
|
|
/*! Last access attempt. Identifier provided by MCU application. 0 if info not available. */
|
|
uint16 u16LastAccessId;
|
|
/*! Was the last access attempt successful? */
|
|
uint8 u8Success;
|
|
/*! Did the last access attempt result in modified WINC flash? */
|
|
uint8 u8Changed;
|
|
/*! Has the module been initialized? */
|
|
uint8 u8Init;
|
|
/*! Has the module been initialized more recently than the module last reset the WINC? */
|
|
uint8 u8Reset;
|
|
}tstrFlashState;
|
|
|
|
/**@}
|
|
*/
|
|
|
|
/*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*
|
|
FUNCTION PROTOTYPES
|
|
*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*=*/
|
|
/** \defgroup FLASHFUNCTIONS Functions
|
|
* @ingroup FLASHAPI
|
|
*/
|
|
|
|
/**@{*/
|
|
/*!
|
|
@fn \
|
|
sint8 m2m_flash_updateimage(uint8 u8Options, uint16 u16Id, tpfDataAccessFn pfSourceFn, uint32 u32SourceSize);
|
|
|
|
@brief Write/validate/switch a WINC firmware image.
|
|
|
|
@param [in] u8Options
|
|
Flags indicating the required combination of write / validate / switch.
|
|
@param [in] u16Id
|
|
Transfer identifier, not interpreted by this module.
|
|
@param [in] pfSourceFn
|
|
Function for the module to call to obtain the image from the MCU application.
|
|
@param [in] u32SourceSize
|
|
Size of the image being provided by the MCU application.
|
|
|
|
@see FLASH_UPDATEIMAGE_OPTION_UPDATE
|
|
@see FLASH_UPDATEIMAGE_OPTION_VALIDATE
|
|
@see FLASH_UPDATEIMAGE_OPTION_SWITCH
|
|
|
|
@return Zero indicates success.
|
|
Negative values indicate failure.
|
|
*/
|
|
sint8 m2m_flash_updateimage(uint8 u8Options, uint16 u16Id, tpfDataAccessFn pfSourceFn, uint32 u32SourceSize);
|
|
/*!
|
|
@fn \
|
|
sint8 m2m_flash_readimage(tenuImageId enuImageId, uint16 u16Id, tpfDataAccessFn pfDestFn, uint32 u32DestSize);
|
|
|
|
@brief Read a WINC firmware image.
|
|
|
|
@param [in] enuImageId
|
|
Which partition to read image from.
|
|
@param [in] u16Id
|
|
Transfer identifier, not interpreted by this module.
|
|
@param [in] pfDestFn
|
|
Function for the module to call to send the image to the MCU application.
|
|
@param [in] u32DestSize
|
|
Size of the memory available to the MCU application for storing the image.
|
|
|
|
@return Zero indicates success.
|
|
Negative values indicate failure.
|
|
*/
|
|
sint8 m2m_flash_readimage(tenuImageId enuImageId, uint16 u16Id, tpfDataAccessFn pfDestFn, uint32 u32DestSize);
|
|
/*!
|
|
@fn \
|
|
sint8 m2m_flash_rootcert_add(uint16 u16Id, tpfDataAccessFn pfSourceFn, uint32 u32SourceSize);
|
|
|
|
@brief Add an entry to the WINC TLS root certificate store.
|
|
|
|
@param [in] u16Id
|
|
Transfer identifier, not interpreted by this module.
|
|
@param [in] pfSourceFn
|
|
Function for the module to call to obtain the certificate entry from the MCU application.
|
|
@param [in] u32SourceSize
|
|
Size of the certificate entry being provided by the MCU application.
|
|
|
|
@note The data location to be accessed via pfSourceFn
|
|
contains the entry to be added. The format of a TLS root certificate entry is:
|
|
@code{.c}
|
|
Name Offset Length Contents
|
|
Header 0 36 tstrRootCertEntryHeader
|
|
Key 36 KeyLength Public key and padding
|
|
Padding 36+KeyLength PadLength 0xFF
|
|
@endcode
|
|
For RSA public keys, the format of Key is:
|
|
@code{.c}
|
|
Name Offset Length
|
|
Modulus 36 ModLength RSA modulus, with leading 0s stripped off
|
|
Exponent 36+ModLength ExpLength Public exponent, with leading 0s stripped off
|
|
@endcode
|
|
In this case PadLength is the amount of padding that would be required for 4-byte alignment of Modulus
|
|
plus the amount of padding that would be required for 4-byte alignment of Exponent.\n
|
|
For ECDSA public keys, the format of Key is:
|
|
@code{.c}
|
|
Name Offset Length
|
|
X Coord 36 CoordLength Public key X-coordinate
|
|
Y Coord 36+CoordLength CoordLength Public key Y-coordinate
|
|
@endcode
|
|
In this case PadLength is the amount of padding that would be required for 4-byte alignment of X Coord
|
|
plus the amount of padding that would be required for 4-byte alignment of Y Coord.
|
|
|
|
@return Zero indicates success.
|
|
Negative values indicate failure.
|
|
*/
|
|
sint8 m2m_flash_rootcert_add(uint16 u16Id, tpfDataAccessFn pfFn, uint32 u32Size);
|
|
|
|
/*!
|
|
@fn \
|
|
sint8 m2m_flash_rootcert_remove(uint16 u16Id, uint8 *pu8Identifier, uint32 u32IdentifierSz);
|
|
|
|
@brief Remove an entry from the WINC TLS root certificate store.
|
|
|
|
@param [in] u16Id
|
|
Transfer identifier, not interpreted by this module.
|
|
@param [in] pu8Identifier
|
|
Identifier for the entry to be removed. This is the SHA1 digest of the certificate issuer name.
|
|
@param [in] u32IdentifierSz
|
|
Size of the identifier (20).
|
|
|
|
@return Zero indicates success.
|
|
Negative values indicate failure.
|
|
*/
|
|
sint8 m2m_flash_rootcert_remove(uint16 u16Id, uint8 *pu8Identifier, uint32 u32IdentifierSz);
|
|
/*!
|
|
@fn \
|
|
sint8 m2m_flash_rootcert_read(uint16 u16Id, tpfDataAccessFn pfDestFn, uint32 u32DestSize, uint8 *pu8Identifier, uint32 u32IdentifierSz);
|
|
|
|
@brief Read an entry from the WINC TLS root certificate store, referenced by entry identifier.
|
|
|
|
@param [in] u16Id
|
|
Transfer identifier, not interpreted by this module.
|
|
@param [in] pfDestFn
|
|
Function for the module to call to send the certificate entry to the MCU application.
|
|
@param [in] u32DestSize
|
|
Size of the memory available to the MCU application for storing the entry.
|
|
@param [in] pu8Identifier
|
|
Identifier for the entry to be read. This is the SHA1 digest of the certificate issuer name.
|
|
@param [in] u32IdentifierSz
|
|
Size of the identifier (20).
|
|
|
|
@return Zero indicates success.
|
|
Negative values indicate failure.
|
|
*/
|
|
sint8 m2m_flash_rootcert_read(uint16 u16Id, tpfDataAccessFn pfDestFn, uint32 u32DestSize, uint8 *pu8Identifier, uint32 u32IdentifierSz);
|
|
/*!
|
|
@fn \
|
|
sint8 m2m_flash_rootcert_readidx(uint16 u16Id, tpfDataAccessFn pfDestFn, uint32 u32DestSize, uint8 u8Index);
|
|
|
|
@brief Read an entry from the WINC TLS root certificate store, referenced by entry index.
|
|
|
|
@param [in] u16Id
|
|
Transfer identifier, not interpreted by this module.
|
|
@param [in] pfDestFn
|
|
Function for the module to call to send the certificate entry to the MCU application.
|
|
@param [in] u32DestSize
|
|
Size of the memory available to the MCU application for storing the entry.
|
|
@param [in] u8Index
|
|
Zero-based index of the entry to be read.
|
|
|
|
@return Zero indicates success.
|
|
Negative values indicate failure.
|
|
*/
|
|
sint8 m2m_flash_rootcert_readidx(uint16 u16Id, tpfDataAccessFn pfDestFn, uint32 u32DestSize, uint8 u8Index);
|
|
|
|
/*!
|
|
@fn \
|
|
void m2m_flash_get_state(tstrFlashState *pstrState);
|
|
|
|
@brief Get information about the module current state and about the most recent access attempt.
|
|
|
|
@param [out] pstrState
|
|
Module state and most recent access attempt info.
|
|
|
|
@return None.
|
|
*/
|
|
void m2m_flash_get_state(tstrFlashState *pstrState);
|
|
|
|
|
|
/*!
|
|
@fn \
|
|
sint8 m2m_flash_init(void);
|
|
|
|
@brief Initialize the module.
|
|
|
|
@warning This API must be called at a particular point during MCU application initialization.
|
|
|
|
@see m2m_wifi_init
|
|
@see m2m_wifi_init_hold
|
|
@see m2m_wifi_init_start
|
|
|
|
\section FlashExample2 Example
|
|
This example demonstrates how to add @ref m2m_flash_init and @ref m2m_flash_get_state
|
|
to MCU application initialization code.
|
|
|
|
Original code:
|
|
@code{.c}
|
|
{
|
|
tstrWifiInitParam param = {...}
|
|
sint8 status = 0;
|
|
|
|
status = m2m_wifi_init(param);
|
|
if (status != 0)
|
|
{
|
|
// Wifi init failed.
|
|
}
|
|
}
|
|
@endcode
|
|
New code:
|
|
@code{.c}
|
|
{
|
|
tstrWifiInitParam param = {...}
|
|
sint8 status = 0;
|
|
|
|
status = m2m_wifi_init_hold();
|
|
if (status == 0)
|
|
{
|
|
tstrFlashState strFlashState;
|
|
|
|
m2m_flash_get_state(&strFlashState);
|
|
printf("FlashAccess:%x:%d%d\n", strFlashState.u16LastAccessId, strFlashState.u8Success, strFlashState.u8Changed);
|
|
|
|
switch (strFlashState.u16LastAccessId)
|
|
{
|
|
// Application code dependent on meaning of u16LastAccessId.
|
|
}
|
|
m2m_flash_init();
|
|
status = m2m_wifi_init_start(param);
|
|
}
|
|
if (status != 0)
|
|
{
|
|
// Wifi init failed.
|
|
}
|
|
}
|
|
@endcode
|
|
|
|
@return Zero for successful initialization of module. Negative value otherwise.
|
|
*/
|
|
sint8 m2m_flash_init(void);
|
|
|
|
/**@}*/
|
|
#endif /* __M2M_FLASH_H__ */
|