- toolkit V2.8.0.1@14806 - BSL V1.8.0.0@14590 - tcpserver: V1.4.3.0@14676 (marshaller V2.4.0.1@14551)
459 lines
18 KiB
C
459 lines
18 KiB
C
/**************************************************************************************
|
|
|
|
Copyright (c) Hilscher Gesellschaft fuer Systemautomation mbH. All Rights Reserved.
|
|
|
|
***************************************************************************************
|
|
|
|
$Id: $:
|
|
|
|
Description:
|
|
cifX Toolkit implementation of the netX50/51 boot functions
|
|
|
|
Changes:
|
|
Date Description
|
|
-----------------------------------------------------------------------------------
|
|
2021-08-31 IsNetX51or52ROM() sets now eChipType in device instance after checking
|
|
2018-09-24 moved hboot functions to separate module
|
|
|
|
|
|
**************************************************************************************/
|
|
|
|
#include "cifXToolkit.h"
|
|
#include "NetX_ROMLoader.h"
|
|
#include "netx50_romloader_dpm.h"
|
|
#include "netx51_romloader_dpm.h"
|
|
#include "cifXErrors.h"
|
|
#include "cifXEndianess.h"
|
|
|
|
/*****************************************************************************/
|
|
/*! Structure describing a single HBOOT DPM mailbox */
|
|
/*****************************************************************************/
|
|
typedef struct HBOOT_MBX_DATA_Ttag
|
|
{
|
|
uint8_t bHskMask; /*!< Handshake bit to toggle for this mailbox */
|
|
uint32_t ulSize; /*!< Total size of mailbox */
|
|
void* pvData; /*!< Data area of mailbox */
|
|
volatile uint32_t* pulDataLen; /*!< Used size of mailbox */
|
|
} HBOOT_MBX_DATA_T;
|
|
|
|
/*****************************************************************************/
|
|
/*! Structure describing HBOOT DPM */
|
|
/*****************************************************************************/
|
|
typedef struct HBOOT_DATA_Ttag
|
|
{
|
|
HBOOT_HSREGISTER_T* ptHsk; /*!< Handshake cell */
|
|
HBOOT_MBX_DATA_T tToNetXMailbox; /*!< Mailbox information Host-->netX */
|
|
HBOOT_MBX_DATA_T tToHostMailbox; /*!< Mailbox information netX-->Host */
|
|
|
|
} HBOOT_DATA_T;
|
|
|
|
/*****************************************************************************/
|
|
/*! Detect a running netX51/52 ROMLoader via DPM
|
|
* \param ptDevInstance Instance to reset
|
|
* \return !=0 if netX51/52 has been detected */
|
|
/*****************************************************************************/
|
|
int IsNetX51or52ROM(PDEVICEINSTANCE ptDevInstance)
|
|
{
|
|
int iRet = 0;
|
|
NETX51_DPM_CONFIG_AREA_T* ptDpmCfg = (NETX51_DPM_CONFIG_AREA_T*)ptDevInstance->pbDPM;
|
|
|
|
if( (HWIF_READ8(ptDevInstance, ptDevInstance->pbDPM[NETX51_DETECT_OFFSET1]) == NETX51_DETECT_VALUE1) &&
|
|
(HWIF_READ8(ptDevInstance, ptDevInstance->pbDPM[NETX51_DETECT_OFFSET2]) == NETX51_DETECT_VALUE2) &&
|
|
(HWIF_READ32(ptDevInstance, ptDpmCfg->aulReserved1[0]) == 0) &&
|
|
(HWIF_READ32(ptDevInstance, ptDpmCfg->aulReserved1[1]) == 0) )
|
|
{
|
|
/* We found a valid entry */
|
|
/* Check for netX51 or netX52 */
|
|
uint32_t ulDpmNetxVersion = (MSK_NX56_dpm_netx_version_valid | MSK_NX56_dpm_netx_version_chiptype) &
|
|
HWIF_READ32(ptDevInstance, ptDpmCfg->ulDpmNetxVersion);
|
|
|
|
if ( (MSK_NX56_dpm_netx_version_valid | ( 2 << SRT_NX56_dpm_netx_version_chiptype)) == ulDpmNetxVersion )
|
|
{
|
|
/* This is a netX52 */
|
|
ptDevInstance->eChipType = eCHIP_TYPE_NETX52;
|
|
} else
|
|
{
|
|
/* This is a netX51 */
|
|
ptDevInstance->eChipType = eCHIP_TYPE_NETX51;
|
|
}
|
|
|
|
iRet = 1;
|
|
}
|
|
|
|
return iRet;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*! Wait for bitstate in netX50/51 ROMloader (hboot) DPM
|
|
* \param ptDevInstance Instance to download the bootloader to (needs a reset
|
|
* before downloading)
|
|
* \param ptHbootData Romloader boot data structure
|
|
* \param ulBitMask Bitmask to check
|
|
* \param bState Required state (HIL_FLAGS_EQUAL/NOT_EQUAL are supported
|
|
* \param ulTimeout Timeout in ms to wait for packet
|
|
* \return !=0 on success */
|
|
/*****************************************************************************/
|
|
static int hboot_waitforbitstate(PDEVICEINSTANCE ptDevInstance,
|
|
HBOOT_DATA_T* ptHbootData,
|
|
uint32_t ulBitMask,
|
|
uint8_t bState,
|
|
uint32_t ulTimeout)
|
|
{
|
|
int iRet = 0;
|
|
int32_t lStartTime = 0;
|
|
HBOOT_HSREGISTER_T* ptHsk = ptHbootData->ptHsk;
|
|
uint8_t bActualState = 0;
|
|
uint8_t bHostFlags = 0;
|
|
|
|
UNREFERENCED_PARAMETER(ptDevInstance);
|
|
|
|
bHostFlags = HWIF_READ8(ptDevInstance, ptHsk->t8Bit.bHostFlags);
|
|
if((bHostFlags ^ HWIF_READ8(ptDevInstance, ptHsk->t8Bit.bNetXFlags)) & ulBitMask)
|
|
bActualState = HIL_FLAGS_NOT_EQUAL;
|
|
else
|
|
bActualState = HIL_FLAGS_EQUAL;
|
|
|
|
/* The desired state is already there, so just return true */
|
|
if(bActualState == bState)
|
|
return 1;
|
|
|
|
/* If no timeout is given, don't try to wait for the Bit change */
|
|
if(0 == ulTimeout)
|
|
return 0;
|
|
|
|
lStartTime = (int32_t)OS_GetMilliSecCounter();
|
|
|
|
/* Poll for desired bit state */
|
|
while(bActualState != bState)
|
|
{
|
|
uint32_t ulDiffTime = 0L;
|
|
|
|
bHostFlags = HWIF_READ8(ptDevInstance, ptHsk->t8Bit.bHostFlags);
|
|
if((bHostFlags ^ HWIF_READ8(ptDevInstance, ptHsk->t8Bit.bNetXFlags)) & ulBitMask)
|
|
bActualState = HIL_FLAGS_NOT_EQUAL;
|
|
else
|
|
bActualState = HIL_FLAGS_EQUAL;
|
|
|
|
/* Check for timeout */
|
|
ulDiffTime = OS_GetMilliSecCounter() - lStartTime;
|
|
if ( ulDiffTime > ulTimeout)
|
|
{
|
|
break;
|
|
}
|
|
|
|
OS_Sleep(0);
|
|
}
|
|
|
|
if(bActualState == bState)
|
|
iRet = 1;
|
|
|
|
return iRet;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*! Send a packet to the netX50/51 romloader (hboot)
|
|
* \param ptDevInstance Instance to download the bootloader to (needs a reset
|
|
* before downloading)
|
|
* \param ptHbootData Romloader boot data structure
|
|
* \param pbData Send data buffer
|
|
* \param ulDataLen Length of send data
|
|
* \param ulTimeout Timeout in ms to wait for packet
|
|
* \return CIFX_NO_ERROR on success */
|
|
/*****************************************************************************/
|
|
static int32_t hboot_send_packet(PDEVICEINSTANCE ptDevInstance,
|
|
HBOOT_DATA_T* ptHbootData,
|
|
uint8_t* pbData,
|
|
uint32_t ulDataLen,
|
|
uint32_t ulTimeout)
|
|
{
|
|
int32_t lRet = CIFX_NO_ERROR;
|
|
HBOOT_HSREGISTER_T* ptHsk = ptHbootData->ptHsk;
|
|
uint8_t bToNetXMask = ptHbootData->tToNetXMailbox.bHskMask;
|
|
uint32_t ulMailboxSize = ptHbootData->tToNetXMailbox.ulSize;
|
|
void* pvMailbox = ptHbootData->tToNetXMailbox.pvData;
|
|
volatile uint32_t* pulMbxDataLen = ptHbootData->tToNetXMailbox.pulDataLen;
|
|
|
|
if(ulDataLen > ulMailboxSize)
|
|
return CIFX_INVALID_BUFFERSIZE;
|
|
|
|
if(!hboot_waitforbitstate(ptDevInstance,
|
|
ptHbootData,
|
|
bToNetXMask,
|
|
HIL_FLAGS_EQUAL,
|
|
ulTimeout))
|
|
{
|
|
/* The mailbox is busy */
|
|
lRet = CIFX_DEV_PUT_TIMEOUT;
|
|
|
|
} else
|
|
{
|
|
uint8_t bHostFlags = 0;
|
|
|
|
/* The mailbox is free */
|
|
HWIF_WRITEN(ptDevInstance,
|
|
pvMailbox,
|
|
pbData,
|
|
ulDataLen);
|
|
|
|
HWIF_WRITE32(ptDevInstance, pulMbxDataLen[0], HOST_TO_LE32(ulDataLen));
|
|
|
|
bHostFlags = HWIF_READ8(ptDevInstance, ptHsk->t8Bit.bHostFlags);
|
|
HWIF_WRITE8(ptDevInstance, ptHsk->t8Bit.bHostFlags, (bHostFlags ^ bToNetXMask));
|
|
|
|
lRet = CIFX_NO_ERROR;
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*! Get a packet from the netX50/51 romloader (hboot)
|
|
* \param ptDevInstance Instance to download the bootloader to (needs a reset
|
|
* before downloading)
|
|
* \param ptHBootData Romloader boot data structure
|
|
* \param pbResult Buffer for romloader error
|
|
* \param ulTimeout Timeout in ms to wait for packet
|
|
* \return CIFX_NO_ERROR on success */
|
|
/*****************************************************************************/
|
|
static int32_t hboot_get_packet(PDEVICEINSTANCE ptDevInstance,
|
|
HBOOT_DATA_T* ptHBootData,
|
|
uint8_t* pbResult,
|
|
uint32_t ulTimeout)
|
|
{
|
|
int32_t lRet = CIFX_DEV_GET_NO_PACKET;
|
|
|
|
if(hboot_waitforbitstate(ptDevInstance,
|
|
ptHBootData,
|
|
NETX50_DPM_TOHOSTMBX_MSK,
|
|
HIL_FLAGS_NOT_EQUAL,
|
|
ulTimeout))
|
|
{
|
|
HBOOT_HSREGISTER_T* ptHskReg = ptHBootData->ptHsk;
|
|
volatile uint8_t* pbMailbox = (volatile uint8_t*)ptHBootData->tToHostMailbox.pvData;
|
|
volatile uint32_t* pulMbxDataLen = ptHBootData->tToHostMailbox.pulDataLen;
|
|
uint8_t bToHostMask = ptHBootData->tToHostMailbox.bHskMask;
|
|
uint8_t bHostFlags = 0;
|
|
|
|
lRet = CIFX_NO_ERROR;
|
|
|
|
if( LE32_TO_HOST(HWIF_READ32(ptDevInstance, pulMbxDataLen[0])) != 1)
|
|
{
|
|
lRet = CIFX_DRV_INIT_STATE_ERROR;
|
|
|
|
} else
|
|
{
|
|
*pbResult = HWIF_READ8(ptDevInstance, pbMailbox[0]);
|
|
}
|
|
|
|
bHostFlags = HWIF_READ8(ptDevInstance, ptHskReg->t8Bit.bHostFlags);
|
|
if((bHostFlags ^ HWIF_READ8(ptDevInstance, ptHskReg->t8Bit.bNetXFlags)) & bToHostMask)
|
|
{
|
|
HWIF_WRITE8(ptDevInstance, ptHskReg->t8Bit.bHostFlags, (bHostFlags ^ bToHostMask));
|
|
}
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*! Exchanges a packet with the netX50/51 romloader (hboot)
|
|
* \param ptDevInstance Instance to download the bootloader to (needs a reset
|
|
* before downloading)
|
|
* \param ptHBootData Romloader boot data structure
|
|
* \param pbSendData Send data buffer
|
|
* \param ulSendDataLen Send data length
|
|
* \param pbResult Buffer for romloader error
|
|
* \param ulTimeout Timeout in ms to wait for packet
|
|
* \return CIFX_NO_ERROR on success */
|
|
/*****************************************************************************/
|
|
static int32_t hboot_transfer_packet(PDEVICEINSTANCE ptDevInstance,
|
|
HBOOT_DATA_T* ptHBootData,
|
|
uint8_t* pbSendData,
|
|
uint32_t ulSendDataLen,
|
|
uint8_t* pbResult,
|
|
uint32_t ulTimeout)
|
|
{
|
|
int32_t lRet = CIFX_NO_ERROR;
|
|
|
|
if(CIFX_NO_ERROR == (lRet = hboot_send_packet(ptDevInstance, ptHBootData, pbSendData, ulSendDataLen, ulTimeout)))
|
|
{
|
|
lRet = hboot_get_packet(ptDevInstance, ptHBootData, pbResult, ulTimeout);
|
|
}
|
|
|
|
return lRet;
|
|
}
|
|
|
|
/*****************************************************************************/
|
|
/*! Downloads and starts the bootloader on netX50/51 (hboot)
|
|
* \param ptDevInstance Instance to download the bootloader to (needs a reset
|
|
* before downloading)
|
|
* \param pbFileData Pointer to bootloader file data
|
|
* \param ulFileDataLen Length of bootloader file
|
|
* \return CIFX_NO_ERROR on success */
|
|
/*****************************************************************************/
|
|
int32_t cifXStartBootloader_hboot(PDEVICEINSTANCE ptDevInstance,
|
|
uint8_t* pbFileData,
|
|
uint32_t ulFileDataLen)
|
|
{
|
|
int32_t lRet = CIFX_NO_ERROR;
|
|
uint32_t ulCopyLen = 0;
|
|
HBOOT_DATA_T tHBoot;
|
|
|
|
OS_Memset(&tHBoot, 0, sizeof(tHBoot));
|
|
|
|
/* Check for chip type and initialize boot data structure */
|
|
if((eCHIP_TYPE_NETX51 == ptDevInstance->eChipType) || (eCHIP_TYPE_NETX52 == ptDevInstance->eChipType))
|
|
{
|
|
PNETX51_ROMLOADER_DPM ptDpm = (PNETX51_ROMLOADER_DPM)ptDevInstance->pbDPM;
|
|
|
|
tHBoot.ptHsk = (HBOOT_HSREGISTER_T*)&ptDpm->tHandshake.ulHandshakeFlag;
|
|
|
|
tHBoot.tToHostMailbox.bHskMask = NETX51_DPM_TOHOSTMBX_MSK;
|
|
tHBoot.tToHostMailbox.pulDataLen = &ptDpm->tHBootConfig.ulNetXToHostDataSize;
|
|
tHBoot.tToHostMailbox.pvData = (void*)ptDpm->abNetxToHostData;
|
|
tHBoot.tToHostMailbox.ulSize = sizeof(ptDpm->abNetxToHostData);
|
|
|
|
tHBoot.tToNetXMailbox.bHskMask = NETX51_DPM_TONETXMBX_MSK;
|
|
tHBoot.tToNetXMailbox.pulDataLen = &ptDpm->tHBootConfig.ulHostToNetxDataSize;
|
|
tHBoot.tToNetXMailbox.pvData = (void*)ptDpm->abHostToNetxData;
|
|
tHBoot.tToNetXMailbox.ulSize = sizeof(ptDpm->abHostToNetxData);
|
|
|
|
if(g_ulTraceLevel & TRACE_LEVEL_DEBUG)
|
|
{
|
|
USER_Trace(ptDevInstance,
|
|
TRACE_LEVEL_DEBUG,
|
|
"Found netX51 ROMloader");
|
|
}
|
|
} else
|
|
{
|
|
PNETX50_ROMLOADER_DPM ptDpm = (PNETX50_ROMLOADER_DPM)ptDevInstance->pbDPM;
|
|
|
|
tHBoot.ptHsk = &ptDpm->atHandshakeRegs[NETX50_DPM_HANDSHAKE_OFFSET];
|
|
|
|
tHBoot.tToHostMailbox.bHskMask = NETX50_DPM_TOHOSTMBX_MSK;
|
|
tHBoot.tToHostMailbox.pulDataLen = &ptDpm->ulNetxToHostDataSize;
|
|
tHBoot.tToHostMailbox.pvData = (void*)ptDpm->abNetxToHostData;
|
|
tHBoot.tToHostMailbox.ulSize = sizeof(ptDpm->abNetxToHostData);
|
|
|
|
tHBoot.tToNetXMailbox.bHskMask = NETX50_DPM_TONETXMBX_MSK;
|
|
tHBoot.tToNetXMailbox.pulDataLen = &ptDpm->ulHostToNetxDataSize;
|
|
tHBoot.tToNetXMailbox.pvData = (void*)ptDpm->abHostToNetxData;
|
|
tHBoot.tToNetXMailbox.ulSize = sizeof(ptDpm->abHostToNetxData);
|
|
|
|
/* Read romloader version */
|
|
if(g_ulTraceLevel & TRACE_LEVEL_DEBUG)
|
|
{
|
|
uint32_t ulLayout = LE32_TO_HOST(HWIF_READ32(ptDevInstance, ptDpm->aulDpmHsRegs[NETX50_DPM_BLLAYOUT_OFFSET]));
|
|
ulLayout = (ulLayout & MSK_NETX50_DPM_BLLAYOUT) >> SRT_NETX50_DPM_BLLAYOUT;
|
|
|
|
USER_Trace(ptDevInstance,
|
|
TRACE_LEVEL_DEBUG,
|
|
"Found netX50 ROMloader, DPM layout type 0x%08X",
|
|
ulLayout);
|
|
}
|
|
}
|
|
|
|
ulCopyLen = tHBoot.tToNetXMailbox.ulSize;
|
|
|
|
if(ulFileDataLen < sizeof(NETX_BOOTBLOCK_T))
|
|
{
|
|
USER_Trace(ptDevInstance,
|
|
TRACE_LEVEL_ERROR,
|
|
"Invalid Bootloader file. File must be larger than 64 Bytes. (Detected Size:%u)",
|
|
ulFileDataLen);
|
|
lRet = CIFX_FILE_TYPE_INVALID;
|
|
}
|
|
|
|
if(CIFX_NO_ERROR == lRet)
|
|
{
|
|
uint8_t bResult = 0;
|
|
int fLastPacketReceived = 0;
|
|
|
|
/* Send Bootblock to device */
|
|
if(CIFX_NO_ERROR != (lRet = hboot_transfer_packet(ptDevInstance,
|
|
&tHBoot,
|
|
pbFileData,
|
|
sizeof(NETX_BOOTBLOCK_T),
|
|
&bResult,
|
|
CIFX_TO_SEND_PACKET)))
|
|
{
|
|
USER_Trace(ptDevInstance,
|
|
TRACE_LEVEL_ERROR,
|
|
"Error transfering bootheader to netX50 Bootloader (lRet = 0x%08X)",
|
|
lRet);
|
|
|
|
} else if(0 != bResult)
|
|
{
|
|
USER_Trace(ptDevInstance,
|
|
TRACE_LEVEL_ERROR,
|
|
"netX50 ROMloader rejected bootblock (bResult = %u)",
|
|
bResult);
|
|
lRet = CIFX_DRV_DOWNLOAD_FAILED;
|
|
|
|
} else
|
|
{
|
|
/* Everything ok. start with rest of file */
|
|
pbFileData += (uint32_t)sizeof(NETX_BOOTBLOCK_T);
|
|
ulFileDataLen -= (uint32_t)sizeof(NETX_BOOTBLOCK_T);
|
|
}
|
|
|
|
/* Download whole file and abort if something went wrong during download */
|
|
while( (ulFileDataLen > 0) &&
|
|
(lRet == CIFX_NO_ERROR) )
|
|
{
|
|
/* Last fragment may be shorter */
|
|
if(ulFileDataLen < ulCopyLen)
|
|
ulCopyLen = ulFileDataLen;
|
|
|
|
/* Place message in mailbox and wait until message has been processed */
|
|
lRet = hboot_send_packet(ptDevInstance, &tHBoot, pbFileData, ulCopyLen, CIFX_TO_SEND_PACKET);
|
|
|
|
if(CIFX_NO_ERROR != lRet)
|
|
{
|
|
USER_Trace(ptDevInstance,
|
|
TRACE_LEVEL_ERROR,
|
|
"Error transferring data packet from/to netX50 Bootloader (lRet = 0x%08X)",
|
|
lRet);
|
|
|
|
} else if(CIFX_NO_ERROR == (hboot_get_packet(ptDevInstance, &tHBoot, &bResult, 0)))
|
|
{
|
|
/* Download is finished or has been aborted. Check will be done below */
|
|
fLastPacketReceived = 1;
|
|
break;
|
|
}
|
|
|
|
pbFileData += ulCopyLen;
|
|
ulFileDataLen -= ulCopyLen;
|
|
}
|
|
|
|
if(CIFX_NO_ERROR == lRet)
|
|
{
|
|
if(!fLastPacketReceived &&
|
|
(CIFX_NO_ERROR != (lRet = hboot_get_packet(ptDevInstance, &tHBoot, &bResult, CIFX_TO_SEND_PACKET))) )
|
|
{
|
|
if(g_ulTraceLevel & TRACE_LEVEL_ERROR)
|
|
{
|
|
USER_Trace(ptDevInstance,
|
|
TRACE_LEVEL_ERROR,
|
|
"Error getting final packet from netX50 ROM Loader. lRet=0x%08X",
|
|
lRet);
|
|
}
|
|
|
|
} else if( 0 != bResult)
|
|
{
|
|
if(g_ulTraceLevel & TRACE_LEVEL_ERROR)
|
|
{
|
|
USER_Trace(ptDevInstance,
|
|
TRACE_LEVEL_ERROR,
|
|
"netX50 ROM Loader download error. bResult=%u",
|
|
bResult);
|
|
}
|
|
lRet = CIFX_DRV_DOWNLOAD_FAILED;
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return lRet;
|
|
}
|