| /****************************************************************************** |
| ** |
| ** INTEL CONFIDENTIAL |
| ** Copyright 2003-2004 Intel Corporation All Rights Reserved. |
| ** |
| ** The source code contained or described herein and all documents |
| ** related to the source code (Material) are owned by Intel Corporation |
| ** or its suppliers or licensors. Title to the Material remains with |
| ** Intel Corporation or its suppliers and licensors. The Material contains |
| ** trade secrets and proprietary and confidential information of Intel |
| ** or its suppliers and licensors. The Material is protected by worldwide |
| ** copyright and trade secret laws and treaty provisions. No part of the |
| ** Material may be used, copied, reproduced, modified, published, uploaded, |
| ** posted, transmitted, distributed, or disclosed in any way without Intel's |
| ** prior express written permission. |
| ** |
| ** No license under any patent, copyright, trade secret or other intellectual |
| ** property right is granted to or conferred upon you by disclosure or |
| ** delivery of the Materials, either expressly, by implication, inducement, |
| ** estoppel or otherwise. Any license under such intellectual property rights |
| ** must be express and approved by Intel in writing. |
| ** |
| ** ProtocolManager.c |
| ******************************************************************************/ |
| |
| /****************************************************************************** |
| * |
| * (C)Copyright 2005 - 2011 Marvell. All Rights Reserved. |
| * |
| * THIS IS UNPUBLISHED PROPRIETARY SOURCE CODE OF MARVELL. |
| * The copyright notice above does not evidence any actual or intended |
| * publication of such source code. |
| * This Module contains Proprietary Information of Marvell and should be |
| * treated as Confidential. |
| * The information in this file is provided for the exclusive use of the |
| * licensees of Marvell. |
| * Such users have the right to use, modify, and incorporate this code into |
| * products for purposes authorized by the license agreement provided they |
| * include this notice and the associated copyright notice with any such |
| * product. |
| * The information in this file is provided "AS IS" without warranty. |
| |
| ******************************************************************************/ |
| |
| /****************************************************************************** |
| * |
| * The boot ROM protocol is documented in the boot ROM specification. This |
| * implements the protocol over the USB or UART port. It is expected that |
| * the driver for the port has a minimal set of routines to handle receiving |
| * and responding to commands. This file will interpret the data and prepare |
| * the response data for a particular command. The driver is resonsible for |
| * sending and receiving the data over the port. |
| * |
| * Basic process: |
| * - Interrupt is received from one of the ports |
| * - The HandleRequest routine is called to get the command from the port |
| * - Based on the request type either a download request or a JTAG request |
| * is started. At this point the other ports are disabled until the |
| * request is completed. |
| * |
| * |
| ******************************************************************************/ |
| |
| #include "ProtocolManager.h" |
| #include "Errors.h" |
| #include "misc.h" |
| #include "Flash.h" |
| #include "FM.h" |
| #include "ICU.h" |
| #include "tim.h" |
| #include "PlatformConfig.h" |
| #include "loadoffsets.h" |
| #include "nand.h" |
| #include "downloader.h" |
| #include "TIMDownload.h" |
| |
| |
| #define MAX_RECV_FIFO_LEN (8192) |
| __attribute__((aligned(8)))UINT8 receiveBuff[MAX_RECV_FIFO_LEN]; |
| UCHAR *pRXbuff = receiveBuff; |
| |
| __attribute__((aligned(8)))UINT8 transmitBuff[MAX_RECV_FIFO_LEN]; |
| // Here's how to interprit the version |
| // MAJOR |
| // A (stepping) = 1 |
| // B (stepping) = 2 |
| // C (stepping) = 3 |
| // D (stepping) = 4 |
| // MINOR |
| // This is basically the stepping number, 0=0, 1=1, 2=2 etc |
| // For example: |
| // A0 = 1000 |
| // A1 = 1001 |
| // B2 = 2002 |
| // C0 = 3000 |
| // C2 = 3002 |
| |
| |
| __attribute__((aligned(4))) UINT8_T preambleString[] = { 0x00, 0xD3, 0x02, 0x2B }; |
| UINT8_T upload_config_flash_flag = 0; |
| UINT8_T upload_get_times_flag = 0; |
| UINT8_T upload_times = 1; |
| UINT8_T ResetUE = 0; |
| UINT8_T ResetDelay = 0; |
| extern UINT8_T FlashInitDone; |
| |
| #if NAND_CODE |
| extern UINT_T NandID; |
| #endif |
| |
| #if REPORT_DDR_INFO |
| extern UINT_T swd_ddr_vendor_id, swd_ddr_size, swd_flash_id; |
| #endif |
| |
| static ProtocolISR GProtocolISR; |
| static pProtocolCmd pGProtocolCmd; |
| static __attribute__((aligned(4))) ProtocolRsp GProtocolRsp; |
| static ProtocolMsg GProtocolMsg; |
| static UINT8_T sProtocolError = NoError; |
| |
| //Protocol Manager helper routines - should all be 'inline' routines |
| pProtocolISR getProtocolISR(void) { return &GProtocolISR; } |
| pProtocolCmd getProtocolCmd(void) { return pGProtocolCmd; } |
| pProtocolCmd setProtocolCmd(void *addr) { return pGProtocolCmd = (pProtocolCmd) addr; } |
| pProtocolRsp getProtocolRsp(void) { return &GProtocolRsp; } |
| pProtocolMsg getProtocolMsg(void) { return &GProtocolMsg; } |
| void setProtocolError(UINT8_T Error) { sProtocolError = Error; } |
| UINT8_T getProtocolError(void) { return sProtocolError; } |
| UCHAR * getProtoBuff() { return pRXbuff; } |
| void setProtoBuff(UCHAR* pAddr) { pRXbuff = pAddr; } |
| void resetProtoBuff() { pRXbuff = receiveBuff; } |
| |
| |
| //Protocol Manager reply routines. Will call into USB API to do the actual send |
| UINT_T SendResponse(UINT8_T *pAckBuff, UINT_T size) |
| { |
| P_USBAPI_T pUsbApi = getProtocolISR()->plinkedUSB; |
| |
| //pointer to the current USB Handle |
| pUsbApi->USB_Send((UINT *)pAckBuff, size, pUsbApi); |
| |
| return NoError; |
| } |
| |
| UINT_T SendAck(void) |
| { |
| UINT_T Retval = NoError; |
| pProtocolCmd pCmd = getProtocolCmd(); |
| pProtocolRsp pRsp = getProtocolRsp(); |
| |
| pRsp->Command = pCmd->Command; |
| pRsp->Sequence = pCmd->Sequence; |
| pRsp->CID = pCmd->CID; |
| pRsp->Status = Ack; |
| pRsp->Flags = pRsp->Flags & ~(MESSAGE_FLAG); |
| pRsp->Flags = pRsp->Flags | getProtocolMsg()->MessageFlag; |
| |
| Retval = SendResponse(&pRsp->Command, pRsp->Length + 6); |
| |
| return Retval; |
| } |
| |
| UINT_T SendError(UINT_T ErrorCode){ |
| |
| UINT_T Retval = NoError; |
| UINT_T RspSize; |
| //UINT_T i; |
| pProtocolCmd pCmd = getProtocolCmd(); |
| pProtocolRsp pRsp = getProtocolRsp(); |
| |
| pRsp->Command = pCmd->Command; |
| pRsp->Sequence = pCmd->Sequence; |
| pRsp->CID = pCmd->CID; |
| pRsp->Status = Nack; |
| pRsp->Flags = getProtocolMsg()->MessageFlag; |
| if(ErrorCode) |
| { |
| pRsp->Length = 4; |
| *(UINT16_T*)&pRsp->Data[0] = ErrorCode & 0x0000FFFF; |
| *(UINT16_T*)&pRsp->Data[2] = (ErrorCode & 0xFFFF0000) >> 16; |
| } |
| else |
| pRsp->Length = 0; |
| |
| RspSize = ErrorCode ? 6 + pRsp->Length : 6; |
| Retval = SendResponse(&pRsp->Command, RspSize); |
| |
| return Retval; |
| } |
| |
| |
| //////////////////////////////////////////////////////////////////////// |
| // Functions to handle specific commands |
| //////////////////////////////////////////////////////////////////////// |
| |
| UINT_T HandleGetVersionCmd() |
| { |
| UINT_T Retval= 0, i; |
| pProtocolRsp pRsp; |
| |
| // UINT8_T *Version = (UINT8_T *)(VERSION_OFFSET + BOOTROMBASEADDR); // legacy way to get version info... |
| // Version used to come from BootROM's version info. |
| // But now the BootROM's memory space is unavailable to BootLoader. |
| // Furthermore, it is probably more appropriate to return the version |
| // info of whichever executable is running: BootROM or BootLoader. |
| extern UINT8_T ExecutableVersionInfo[]; // defined in [TBR|BL]_startup.s |
| UINT8_T *pVersion = ExecutableVersionInfo; // new way to get version info. |
| |
| pRsp = getProtocolRsp(); |
| |
| pRsp->Length = 12; |
| memcpy( (void *)&(pRsp->Data[0]), pVersion, 12); |
| |
| #if REPORT_DDR_INFO |
| pRsp->Length += 8; |
| |
| for (i = 0; i < 4; i++) |
| pRsp->Data[12+i] = (swd_ddr_vendor_id >> (8 * i)) & 0xff; |
| |
| for (i = 0; i < 4; i++) |
| pRsp->Data[16+i] = (swd_ddr_size >> (8 * i)) & 0xff; |
| |
| pRsp->Length += 4; |
| |
| for (i = 0; i < 4; i++) |
| pRsp->Data[20+i] = (swd_flash_id >> (8 * i)) & 0xff; |
| #endif |
| |
| Retval = SendAck(); |
| |
| return Retval; |
| } |
| |
| UINT_T HandleSelectImageCmd(UINT_T imageType) |
| { |
| UINT_T Retval; |
| pProtocolRsp pRsp = getProtocolRsp(); |
| |
| pRsp->Length = 4; |
| |
| *(UINT16_T *)&pRsp->Data[0] = imageType & 0x0000FFFF; |
| *(UINT16_T *)&pRsp->Data[2] = (imageType & 0xFFFF0000) >> 16; |
| |
| Retval = SendAck(); |
| |
| return Retval; |
| } |
| |
| UINT_T HandleVerifyImageCmd() |
| { |
| UINT_T Retval= 0; |
| |
| getProtocolRsp()->Length = 0; |
| |
| if(getProtocolCmd()->Data[0] == Nack) |
| getProtocolISR()->ErrorCode = UnknownImageError; |
| |
| Retval = SendAck(); |
| return Retval; |
| |
| } |
| |
| UINT_T HandleDataHeaderCmd() |
| { |
| UINT_T RemainingLen = 0; |
| UINT_T BufferSize = 0; |
| UINT_T NextSize = 0; |
| |
| pProtocolRsp pRsp = getProtocolRsp(); |
| pProtocolISR pISR = getProtocolISR(); |
| pProtocolCmd pCmd = getProtocolCmd(); |
| |
| pRsp->Length = 4; |
| RemainingLen = *(UINT32_T *)&pCmd->Data[0]; |
| |
| //check to make sure the data will fit |
| if(RemainingLen > pISR->MaxImageSize) |
| { |
| AddMessageError(REPORT_NOTIFICATION, DownloadImageTooBigError); |
| SendError(DownloadImageTooBigError); |
| pISR->ErrorCode = DownloadImageTooBigError; |
| return NULL; |
| } |
| |
| pISR->DataLeft = RemainingLen; //DataLeft indicates how much of the total image remains |
| |
| if (pCmd->Flags & FAST_DOWNLOAD) |
| { |
| pRsp->Flags = pRsp->Flags | FAST_DOWNLOAD; |
| pISR->FastDLInProgress = 1; |
| //setup next read for 2KB |
| NextSize = BufferSize = (RemainingLen > FD_BLOCK_SIZE) ? FD_BLOCK_SIZE : RemainingLen; |
| } |
| else |
| { |
| pRsp->Flags = pRsp->Flags & ~FAST_DOWNLOAD; |
| pISR->FastDLInProgress = 0; |
| //setup next read for 2KB |
| BufferSize = (RemainingLen > DATA_BLOCK_SIZE) ? DATA_BLOCK_SIZE : RemainingLen; |
| NextSize = BufferSize + COMMAND_SIZE; |
| } |
| |
| |
| *(UINT16_T*)&pRsp->Data[0] = BufferSize & 0x0000FFFF; |
| *(UINT16_T*)&pRsp->Data[2] = (BufferSize & 0xFFFF0000) >> 16; |
| |
| SendAck(); |
| |
| |
| return NextSize; |
| } |
| |
| UINT_T HandleDataCmd() |
| { |
| UINT_T Retval = 0; |
| |
| getProtocolCmd()->Command = DownloadDataCmd; |
| getProtocolRsp()->Length = 0; |
| |
| SendAck(); |
| return Retval; |
| } |
| |
| UINT_T HandleDoneCmd() |
| { |
| UINT_T Retval= 0; |
| pProtocolISR pISR = getProtocolISR(); |
| |
| getProtocolRsp()->Length = 0; |
| |
| //reset the status flags |
| pISR->PreambleReceived = FALSE; |
| |
| SendAck(); |
| return Retval; |
| |
| } |
| |
| UINT_T HandleMessageCmd(void){ |
| UINT_T Retval= 0; |
| |
| #if VERBOSE_MODE |
| |
| UINT_T mIndex; |
| UINT_T size; |
| UINT_T i; |
| //UINT8_T Buff[LENGTHOFMESSAGES + 6]; |
| UINT8_T *Buff = transmitBuff; |
| pProtocolCmd pCmd = getProtocolCmd(); |
| pProtocolMsg pMsg = getProtocolMsg(); |
| |
| //tool sending extra message commands to catch messages |
| //if we don't have any messages, just NACK the message and continue |
| if(pMsg->NumMessagesQueued == 0){ |
| SendError(0); |
| return NoError; |
| } |
| |
| //must use Buff instead of GProtocolRsp |
| Buff[0] = pCmd->Command; |
| Buff[1] = pCmd->Sequence; |
| Buff[2] = pCmd->CID; |
| Buff[3] = Ack; |
| |
| mIndex = pMsg->CurrentMessageIndex; |
| size = pMsg->Lengths[mIndex]; |
| |
| Buff[5] = size; |
| for(i = 0; i < size; i++) |
| Buff[6+i] = pMsg->Messages[mIndex][i]; |
| |
| //increment the pointer to the new current message |
| pMsg->CurrentMessageIndex++; |
| pMsg->CurrentMessageIndex %= MAXNUMOFMESSAGES; |
| |
| pMsg->NumMessagesQueued--; |
| |
| if(pMsg->NumMessagesQueued == 0) |
| pMsg->MessageFlag = 0; |
| else |
| pMsg->MessageFlag = 1; |
| |
| //mark flags (message flag message type flag ) |
| Buff[4] = (pMsg->MessageFlag | (pMsg->MessageType[mIndex] << 1)); |
| |
| SendResponse(&Buff[0], 6+size); |
| |
| #else // end if VERBOSE_MODE |
| |
| SendError(0); |
| #endif |
| return Retval; |
| } |
| |
| UINT_T HandleDisconnect() |
| { |
| UINT start_time; |
| pProtocolISR pISR = getProtocolISR(); |
| |
| //if there is no linked USB Device, then there was never any protocol transaction |
| if(pISR->plinkedUSB == NULL) |
| return NoError; |
| |
| //check to see if there are queued up messages. |
| if( (pISR->DisconnectReceived == TRUE) && getProtocolMsg()->MessageFlag) |
| { //clear disconnect received flag as we now need to wait for a new one |
| pISR->DisconnectReceived = FALSE; |
| //reply with a NAK to allow messages to get sent |
| SendError(0); |
| } |
| |
| //give the tool a short time to get all the messages and then reply with a disconnect |
| start_time = GetOSCR0(); |
| while(pISR->DisconnectReceived == FALSE) |
| { |
| //if a download is waiting, terminate it and break out of loop: wtptp tool quits on a NACK |
| if(pISR->DLWaiting == TRUE) |
| { |
| SendError(UnknownImageError); |
| break; |
| } |
| |
| if(OSCR0IntervalInSec(start_time, GetOSCR0()) > PM_DISCONNET_MS) |
| break; |
| } |
| |
| //lastly, reply with an ACK |
| if(pISR->DisconnectReceived == TRUE) |
| SendAck(); |
| |
| //need to release PM semaphore and reset all flags! |
| //Semaphore_Release(PROTOCOL_semaphore); |
| memset(pISR, 0, sizeof(ProtocolISR)); |
| |
| return NoError; |
| } |
| |
| /* InitPort() |
| * |
| * Call into the driver to setup the ports and enable interrupts |
| * |
| */ |
| UINT_T InitPort(UINT_T port) |
| { |
| return USBAPI_InitializeDevice(port); |
| } |
| |
| UINT ImageDownloadWaiting(UINT_T media_num) |
| { |
| pProtocolISR pISR = getProtocolISR(); |
| |
| //check to see if a USB is linked and said linked USB is the matching one |
| // if so, return whether a GetVersion request was made (i.e. a download is waiting) |
| if( (pISR->plinkedUSB != NULL) && |
| (pISR->plinkedUSB->bootNum == media_num) ) |
| return pISR->DLWaiting; |
| else |
| return FALSE; |
| } |
| |
| |
| UINT PreambleReceived() |
| { |
| return getProtocolISR()->PreambleReceived; |
| } |
| |
| void ClearPreambleReceived() |
| { |
| getProtocolISR()->PreambleReceived = FALSE; |
| } |
| |
| // ShutdownPorts: shutdown all ports |
| void ShutdownPorts () |
| { |
| //call into USB API to shutdown all enabled USB devices |
| USBAPI_ShutdownAll(); |
| } |
| |
| //Protocol Manager ISR |
| // There are three possible scenarios when this routine is called: |
| // 1. PM is already used by another USB device (unusual scenario) |
| // 2. PM is being used by the calling device (most likely scenario) |
| // 3. PM is free (starting scenario) |
| // The numbered comments in this routine will match up to the three mentioned scenarios |
| void PM_ISR(P_USBAPI_T this, UINT bytes, UINT * buffer) |
| { |
| UINT next_size, dummy = NULL; |
| pProtocolISR pISR = getProtocolISR(); |
| |
| //1. Is someone else using the protocol? |
| if( (pISR->plinkedUSB != this) && (pISR->plinkedUSB != NULL) ) |
| { //Yes. Another USB is using protocol. Transmit a NAK |
| this->USB_Send(&dummy, PREAMBLE_SIZE, this); |
| //reprime so it will try again later |
| this->USB_Receive(buffer, PREAMBLE_SIZE, this); |
| //time to leave |
| return; |
| } |
| |
| //2. We're already good friends |
| if(pISR->plinkedUSB == this) |
| { |
| if((bytes == PREAMBLE_SIZE ) && (pISR->PreambleReceived == FALSE)) |
| { //check the validity of the preamble |
| if( PM_VerifyPreamble((UCHAR *)buffer) ) |
| { //good Preamble! |
| pISR->PreambleReceived = TRUE; |
| // clear out any errors, as a new Preamble mean a new Image DL |
| pISR->ErrorCode = 0; |
| //respond with the preamble |
| SendResponse(preambleString, PREAMBLE_SIZE); |
| //set the pRXBuff to protocol area |
| resetProtoBuff(); |
| //Setup for a new CMD |
| this->USB_Receive((UINT *)getProtoBuff(), this->maxpacketsize, this); |
| } |
| else |
| { //bad Preamble! |
| //Transmit a NAK |
| this->USB_Send(&dummy, PREAMBLE_SIZE, this); |
| //Reset USB control to download again |
| this->USB_Receive(buffer, PREAMBLE_SIZE, this); |
| } |
| } |
| else |
| { |
| //4. call into PM handler |
| next_size = PM_Handler(bytes); |
| |
| //5. call into USBAPI to set up next RECEIVE |
| this->USB_Receive((UINT *)getProtoBuff(), next_size, this); |
| } |
| //all done, exit now |
| return; |
| } |
| |
| //3. Newbie! Must receive a preamble or else we can't be friends. |
| if(pISR->plinkedUSB == NULL) |
| { //check the validity of the preamble |
| if( (bytes == PREAMBLE_SIZE) && PM_VerifyPreamble((UCHAR *)buffer) ) |
| { //good Preamble! |
| pISR->PreambleReceived = TRUE; |
| // clear out any errors, as a new Preamble mean a new Image DL |
| pISR->ErrorCode = 0; |
| //Check out using semaphore and store the USB API pointer |
| pISR->plinkedUSB = this; |
| //Semaphore_Acquire(PROTOCOL_semaphore); |
| //respond with the preamble |
| SendResponse(preambleString, PREAMBLE_SIZE); |
| //set the pRXBuff to protocol area |
| resetProtoBuff(); |
| //Setup for a new CMD |
| this->USB_Receive((UINT *)getProtoBuff(), this->maxpacketsize, this); |
| } |
| else |
| { //Premable was not valid |
| //Transmit a NAK |
| this->USB_Send(&dummy, PREAMBLE_SIZE, this); |
| //Reset USB control to download again |
| this->USB_Receive(buffer, PREAMBLE_SIZE, this); |
| } |
| return; |
| } |
| } |
| |
| |
| // PROTOCOL HANDLER |
| // This routine is the singular handler for protocol commands |
| // - JTAG over USB (CMD 36) |
| // - Image Downloading |
| // |
| // Inputs: |
| // - pUSBhandle: pointer the calling USB handler |
| // - packetlength: length of the packet that triggered this call |
| // Outputs: |
| // - PrimeSize: the size to prime the next input packet for |
| UINT PM_Handler(UINT packetLength) |
| { |
| pProtocolCmd pCmd; |
| pProtocolISR pISR = getProtocolISR(); |
| UINT next_size = pISR->plinkedUSB->maxpacketsize; //defualt is a full packet |
| |
| //1st check if a fast download command is in progress |
| if(pISR->FastDLInProgress) |
| { |
| //Update counters |
| pISR->CurrentTransferAddress += packetLength; |
| pISR->DataLeft -= packetLength; |
| pISR->MaxImageSize = (packetLength > pISR->MaxImageSize) ? 0 : (pISR->MaxImageSize - packetLength); |
| |
| //When DataLeft = 0, then the command is finally finished. respond back |
| if(pISR->DataLeft == 0) |
| { |
| pISR->FastDLInProgress = 0; |
| HandleDataCmd(); //send the response |
| resetProtoBuff(); //restore the location back to protocol area |
| } |
| else |
| { // Fast Download continues... set up info for next descriprots |
| //security check: can only download "MaxImageSize" per image DL. If malicious software tries to download more, |
| //this line of code will restrict the size dTD and force USB NACKs for any additional data |
| next_size = (pISR->DataLeft > pISR->MaxImageSize) ? pISR->MaxImageSize : pISR->DataLeft; |
| next_size = (next_size < FD_BLOCK_SIZE ) ? next_size : FD_BLOCK_SIZE; |
| setProtoBuff((UINT8 *)pISR->CurrentTransferAddress); //set location for USB to put data |
| } |
| return next_size; |
| } |
| |
| //normal commands |
| //Overlay the Command structure over the buffer |
| pCmd = setProtocolCmd(getProtoBuff()); |
| |
| //All normal commands will load the data to the protocol buffer |
| resetProtoBuff(); |
| |
| //Sanity check - make sure the size read in matches the size defined in the ProtocolCmd packet |
| //if ( packetLength != (8+pCmd->Length) ) |
| //{ |
| // pISR->ErrorCode = UnknownProtocolCmd; |
| // SendError(UnknownProtocolCmd); |
| // return next_size; |
| //} |
| |
| // update Interrupt Status Flags |
| //pISR->CurrentCommand = pCmd->Command; |
| |
| switch( pCmd->Command ) |
| { |
| case MessageCmd: |
| //try and send a message |
| // clear the upload command flag for upload |
| pISR->CommandReceived = FALSE; |
| HandleMessageCmd(); |
| break; |
| #if !BOOTROM |
| case ProtocolVersionCmd: |
| // Send the major and minor protocol version bacl |
| HandleProtocolVersionCmd(); |
| break; |
| case GetParametersCmd: |
| // Send Protocol Parameters to host. |
| HandleGetParametersCmd(); |
| break; |
| case GetImageCrcCmd: |
| HandleGetCrcCmd(); |
| break; |
| case GetBadBlockCmd: |
| HandleGetBadBlock(); |
| break; |
| #endif |
| #if JTAG_OVER_JTAG_SUPPORTED |
| case JtagOverMediaCmd: |
| //copy the JTAG data into the JTAG structure |
| memcpy( (void *)pJTAG_CPCData->CommandFromHost, (void*)&pCmd->Data[0], pCmd->Length); |
| Jtag_Media_Handler(); |
| break; |
| #endif |
| case GetVersionCmd: |
| //Indicate that a download is pending, but do NOT respond yet |
| pISR->DLWaiting = TRUE; |
| pISR->CommandReceived = TRUE; // mark it as download command |
| break; |
| case UploadDataHeaderCmd: |
| pISR->DLWaiting = TRUE; // indicate that a upload is pending |
| pISR->CommandReceived = TRUE; // mark it as upload command |
| break; |
| case UploadDataCmd: |
| pISR->CommandReceived = TRUE; // mark it as upload command |
| break; |
| case SelectImageCmd: |
| HandleSelectImageCmd(pISR->CurrentImageID); |
| next_size = 9; //the next command will be larger than normal |
| break; |
| case VerifyImageCmd: |
| HandleVerifyImageCmd(); |
| next_size = 12; //the next command will be larger than normal |
| break; |
| case DataHeaderCmd: |
| next_size = HandleDataHeaderCmd(); |
| if (pISR->FastDLInProgress) //override the download address for fast download |
| setProtoBuff((UINT8 *)pISR->CurrentTransferAddress); //set location for USB to put data |
| break; |
| case DownloadDataCmd: |
| //Note: this will only be triggered for "slow" download. |
| //move data from the buffer to boot address |
| memcpy((void *)(pISR->CurrentTransferAddress), (void*)&pCmd->Data[0], pCmd->Length); |
| //Update counters |
| pISR->CurrentTransferAddress += pCmd->Length; |
| pISR->MaxImageSize -= (pCmd->Length > pISR->MaxImageSize) ? pISR->MaxImageSize : pCmd->Length; |
| HandleDataCmd(); |
| break; |
| case DoneCmd: |
| //Indicate that a download has finished, but do NOT respond yet |
| pISR->DLWaiting = FALSE; |
| pISR->CommandReceived = TRUE; // exit for upload while loop |
| break; |
| case DisconnectCmd: |
| pISR->DisconnectReceived = TRUE; |
| break; |
| default: |
| break; |
| } |
| |
| |
| |
| |
| |
| return next_size; |
| } |
| |
| |
| |
| |
| |
| |
| // PM_ReceiveImage() |
| // |
| // This is the Protocol Recieve image routine. It does the following: |
| // 1. Set the parameters for the download: |
| // -- destination address |
| // -- max size |
| // -- image ID |
| // 2. Check and wait for a pending image download request (GetVersion command from host) |
| // 3. Download will be kicked off by sending the GetVersion response. |
| // 4. Wait until the download has finished (DoneCommand will indicate that) |
| // |
| UINT_T PM_ReceiveImage(UINT_T dummy, UINT_T address, UINT_T size, UINT_T image_id) |
| { |
| UINT retval = NoError, start_time, wait_time = 0; |
| //pProtocolCmd pCmd = getProtocolCmd(); |
| pProtocolISR pISR = getProtocolISR(); |
| |
| //1. set up initial DL perameters: |
| pISR->CurrentTransferAddress = address; |
| pISR->MaxImageSize = size; |
| pISR->CurrentImageID = image_id; |
| |
| //AddMessageCompound((UINT8_T*) ("*** PM_ReceiveImage pISR->CurrentTransferAddress...\0"), pISR->CurrentTransferAddress); |
| |
| do |
| { |
| //2. wait for the download request |
| start_time = GetOSCR0(); |
| do |
| { //Check for timeout |
| if( OSCR0IntervalInMilli(start_time, GetOSCR0()) > PM_DL_STARTTIME_MS ) |
| { |
| retval = PM_ReceiveTimeOutError_1; |
| break; |
| } |
| } |
| while(pISR->DLWaiting == FALSE); |
| |
| //check for an error |
| if(retval != NoError) |
| break; |
| |
| //3. send the Get Version response to kick off the download |
| retval = HandleGetVersionCmd(); |
| |
| //check for an error |
| if(retval != NoError) |
| break; |
| |
| /* |
| * Suppose the worst USB transfer speed is 0.5MB/s(in fact, it's about 12MB/s |
| * for HS mode but should also consider FS mode) |
| * Then, the wait time should not exceed (size / 1024 /4) milli seconds. |
| * The extra 2000 ms is to ensure the wait time is none-zero |
| */ |
| wait_time = (size >> 9) + 2000; |
| |
| //4. Wait for the Image DL to complete or an error |
| start_time = GetOSCR0(); |
| do |
| { //Check for timeout |
| if( OSCR0IntervalInMilli(start_time, GetOSCR0()) > wait_time ) |
| { |
| retval = PM_ReceiveTimeOutError_2; |
| break; |
| } |
| } |
| while( (pISR->DLWaiting == TRUE) && (pISR->ErrorCode == NoError) ); |
| |
| }while(FALSE); |
| |
| //If there is an protocol error, override local error status |
| if(pISR->ErrorCode) |
| retval = pISR->ErrorCode; |
| |
| //clear the flags to indicate an image dl is done |
| pISR->ErrorCode = NoError; |
| pISR->PreambleReceived = FALSE; |
| pISR->DLWaiting = FALSE; |
| |
| //finish off the download by sending either the DONE cmd on success or NAK on failure |
| if(retval == PM_ReceiveTimeOutError_1 || retval == PM_ReceiveTimeOutError_2) |
| SendError(retval); |
| else |
| HandleDoneCmd(); |
| |
| //returns 0 if complete or an error code |
| return retval; |
| } |
| |
| UINT_T GetUploadCommand(void) |
| { |
| UINT_T Retval = NoError; |
| UINT_T StartTime; |
| |
| pProtocolISR pISR = getProtocolISR(); |
| |
| StartTime = GetOSCR0(); //Dummy read to flush potentially bad data |
| StartTime = GetOSCR0(); |
| |
| while(pISR->CommandReceived == FALSE) |
| { |
| Retval = CheckProtocolTimeOut(StartTime); |
| if(Retval != NoError) |
| return Retval; |
| } |
| pISR->CommandReceived = FALSE; |
| |
| return Retval; |
| } |
| |
| /* |
| * HandleDownloadFlow() |
| * |
| * This function will handle a upload request unitl it completes or fails |
| * and return the status |
| */ |
| |
| UINT_T HandleUploadFlow(UINT_T address) |
| { |
| UINT_T Retval = NoError; |
| pProtocolCmd pCmd = getProtocolCmd(); |
| pProtocolISR pISR = getProtocolISR(); |
| |
| pISR->CurrentTransferAddress = address; |
| |
| do{ |
| switch(pCmd->Command) |
| { |
| case UploadDataHeaderCmd: |
| Retval = HandleUploadDataHeaderCmd(); |
| break; |
| case UploadDataCmd: |
| Retval = HandleUploadDataCmd(); |
| break; |
| default: |
| if(pISR->CommandReceived == TRUE) |
| { |
| Retval = SendError(0); |
| Retval = UnknownProtocolCmd; |
| }else |
| Retval = NoError; |
| break; |
| } |
| if(Retval != NoError){ |
| break; |
| } |
| |
| GetUploadCommand(); |
| |
| }while (pCmd->Command != DoneCmd); |
| |
| return Retval; |
| } |
| |
| /** |
| * Debug Commands |
| **/ |
| UINT_T HandleUploadDataHeaderCmd(void) |
| { |
| UINT_T Retval = NoError; |
| pProtocolCmd pCommand; |
| pProtocolISR pISR; |
| UploadDataParameters uploadParams, *pUploadParams; |
| |
| #if NAND_CODE || QSPINAND_CODE || SPINAND_CODE |
| UINT_T spare_size, page_size; |
| UINT_T numbers, total_spare_size; |
| #endif |
| |
| |
| pUploadParams = &uploadParams; |
| pCommand = getProtocolCmd(); |
| pISR = getProtocolISR(); |
| memcpy((void*)pUploadParams,(void*)&pCommand->Data[0],sizeof(UploadDataParameters)); |
| |
| if (!upload_get_times_flag) |
| { |
| upload_times = pUploadParams->Times; // upload_times >= 1 |
| |
| #if USE_SERIAL_DEBUG |
| obm_printf("upload_times: %d\n\r", upload_times); |
| #endif |
| |
| ResetUE = pUploadParams->ResetUE; |
| ResetDelay = pUploadParams->ResetTimeDelay; |
| |
| obm_printf("ResetUE: %d, ResetDelay: %d\n\r", ResetUE, ResetDelay); |
| |
| upload_get_times_flag = 1; |
| } |
| |
| // Are the upload parameters ok? |
| Retval = VerifyUploadParameters(pUploadParams); |
| AddMessageError(REPORT_NOTIFICATION, PlatformBusy); |
| |
| if(Retval != NoError) |
| { |
| AddMessageError(REPORT_NOTIFICATION, PlatformReady); |
| SendError(Retval); |
| return Retval; |
| } |
| else |
| { |
| getProtocolRsp()->Length = 0; |
| SendAck(); |
| } |
| |
| // Copy data requested into upload buffer |
| |
| //AddMessageError(PlatformBusy); |
| //This could take a while |
| |
| if(pUploadParams->Type == UPLOAD_DDR) |
| pISR->CurrentTransferAddress = pUploadParams->Offset; |
| else |
| Retval = CopyUploadDataIntoBuffer(pISR->CurrentTransferAddress, pUploadParams); |
| |
| AddMessageError(REPORT_NOTIFICATION, PlatformReady); |
| // data should in buffer now |
| |
| if(Retval != NoError) |
| { |
| setProtocolError(Retval); |
| // This was probably an error reading from source as UploadParams checked out ok. |
| // Set to No Error so that error can be sent to Host in HandleUploadDataCmd. |
| Retval = NoError; |
| } |
| else |
| { |
| #if NAND_CODE || QSPINAND_CODE || SPINAND_CODE |
| if (upload_nand_spare == TRUE) |
| { |
| spare_size = GetSpareAreaSize(BOOT_FLASH); // get nand spare areas size |
| page_size = GetPageSize(BOOT_FLASH); |
| numbers = pUploadParams->DataSize / page_size; // calculate spare areas number |
| total_spare_size = numbers * spare_size; // total spare size |
| |
| pISR->DataLeft = pUploadParams->DataSize + total_spare_size; // data length + total spare length |
| } |
| else |
| #endif |
| { |
| pISR->DataLeft = pUploadParams->DataSize; |
| } |
| } |
| |
| return Retval; |
| |
| } |
| |
| UINT_T HandleUploadDataCmd(void) |
| { |
| UINT_T Retval = NoError,txDataSize = 0; |
| pProtocolRsp pRsp = (pProtocolRsp)transmitBuff; |
| pProtocolCmd pCmd = getProtocolCmd(); |
| pProtocolISR pISR = getProtocolISR(); |
| |
| Retval = getProtocolError(); |
| if(Retval!= NoError) |
| { |
| // We had a problem reading data for Data Upload |
| SendError(Retval); |
| return Retval; |
| } |
| |
| if(pISR->DataLeft <= 0) |
| { |
| Retval = SeqError; |
| SendError(Retval); |
| return Retval; |
| } |
| |
| pRsp->Command = UploadDataCmd; |
| pRsp->Sequence = pCmd->Sequence; |
| pRsp->CID = pCmd->CID; |
| pRsp->Status = Ack; |
| |
| // Too bad length is only a byte. Not using it. |
| pRsp->Length = 0; |
| |
| txDataSize = pISR->DataLeft < UPLOAD_BLOCK_SIZE ? pISR->DataLeft : UPLOAD_BLOCK_SIZE; |
| // Not a fan but have to do this. We have 6 byte status and arbitrary data. |
| memcpy((void*)&pRsp->Data[0], (void*)pISR->CurrentTransferAddress, txDataSize); |
| |
| |
| // Message bit should NOT be set in flags. |
| // At this point getProtocolMsg()->MessageFlag will be 0. |
| pRsp->Flags = pRsp->Flags & ~(MESSAGE_FLAG); |
| pRsp->Flags = pRsp->Flags | getProtocolMsg()->MessageFlag; |
| |
| Retval = SendResponse(&pRsp->Command, txDataSize + 6); |
| |
| pISR->CurrentTransferAddress += txDataSize; |
| pISR->DataLeft -= txDataSize; |
| |
| return Retval; |
| } |
| |
| UINT_T CopyUploadDataIntoBuffer(UINT_T address, pUploadDataParameters pUploadParams) |
| { |
| UINT_T Retval = NoError; |
| |
| switch(pUploadParams->Type) |
| { |
| case UPLOAD_FLASH: |
| // Fix me. Need code to check if sub type of flash is supported. |
| if (!upload_config_flash_flag && !FlashInitDone) |
| { |
| /* sub type of flash is not supported */ |
| //Retval = PlatformInitFlash(pUploadParams->SubType & 0x1F); |
| Retval = Configure_Flashes(pUploadParams->SubType & 0x1F, BOOT_FLASH); |
| if( Retval != NoError) |
| FatalError(Retval, NULL, NULL); |
| |
| InitializeFM(LEGACY_METHOD, BOOT_FLASH); |
| |
| upload_config_flash_flag = 1; // configure flash for upload only one time |
| } |
| |
| #if NAND_CODE || QSPINAND_CODE || SPINAND_CODE |
| |
| #if NAND_CODE |
| if (pUploadParams->ResetUE == 1) |
| { |
| AddMessageError(REPORT_UPLOAD_NOTIFICATION, NandID); |
| } |
| #endif |
| |
| upload_nand_spare = pUploadParams->IncludeOOB; |
| |
| upload_disable_ecc = pUploadParams->DisableECC; |
| #endif |
| |
| // Set the partition. |
| #if MMC_CODE |
| SetPartition(pUploadParams->Partition, BOOT_FLASH); |
| #endif |
| |
| #if defined(NEZHA701) || defined(NEZHA702) |
| if ((pUploadParams->Offset <= MEP_FALSH_START && |
| pUploadParams->Offset + pUploadParams->DataSize > MEP_FALSH_START) || |
| (pUploadParams->Offset >= MEP_FALSH_START && |
| pUploadParams->Offset < MEP_FALSH_START + MEP_FLASH_LEN)) |
| Retval = NotSupportedError; |
| else |
| #endif |
| Retval = ReadFlash(pUploadParams->Offset, address, pUploadParams->DataSize, BOOT_FLASH); |
| break; |
| default: |
| // Not supported. |
| Retval = NotSupportedError; |
| break; |
| |
| } |
| return Retval; |
| } |
| |
| UINT_T VerifyUploadParameters(pUploadDataParameters pUploadParams) |
| { |
| UINT_T Retval = NoError, flashNum; |
| pTIM pTIM_h = GetTimPointer(); |
| switch(pUploadParams->Type) |
| { |
| case UPLOAD_FLASH: |
| // Is flash subtype supported. Looking in Tim. |
| flashNum = pTIM_h->pConsTIM->FlashInfo.BootFlashSign & 0xFF; |
| if(flashNum != pUploadParams->SubType & 0xFF && |
| flashNum != CI2_USB_D) //Empty board upload |
| Retval = UnsupportedFlashError; |
| |
| if(pUploadParams->UploadBypassBBT) { |
| obm_printf("Upload Flash with BBT bypassed\n\r"); |
| GetFlashProperties(BOOT_FLASH)->FlashSettings.UseBBM = 0; |
| } |
| break; |
| case UPLOAD_DDR: |
| break; |
| default: |
| // Not supported. |
| Retval = NotSupportedError; |
| break; |
| |
| } |
| return Retval; |
| } |
| |
| UINT_T HandleProtocolVersionCmd() |
| { |
| UINT_T Retval = 0; |
| pProtocolRsp pRsp; |
| pProtocolCmd pCmd; |
| |
| pCmd = getProtocolCmd(); |
| pRsp = getProtocolRsp(); |
| |
| pRsp->Command = pCmd->Command; |
| pRsp->Sequence = pCmd->Sequence; |
| pRsp->CID = pCmd->CID; |
| pRsp->Status = Ack; |
| pRsp->Length = 4; |
| |
| pRsp->Data[0] = COMM_PROTOCOL_MAJOR_VERSION; |
| pRsp->Data[1] = COMM_PROTOCOL_MINOR_VERSION; |
| *(UINT16_T*)&pRsp->Data[2] = COMM_PROTOCOL_REV_VERSION; |
| |
| pRsp->Flags = pRsp->Flags & ~(MESSAGE_FLAG); |
| pRsp->Flags = pRsp->Flags | getProtocolMsg()->MessageFlag; |
| |
| SendResponse(&pRsp->Command, 6 + pRsp->Length); |
| return Retval; |
| } |
| |
| UINT_T HandleGetParametersCmd() |
| { |
| UINT_T Retval = 0; |
| pProtocolRsp pRsp; |
| pProtocolCmd pCmd; |
| |
| pCmd = getProtocolCmd(); |
| pRsp = getProtocolRsp(); |
| |
| pRsp->Command = pCmd->Command; |
| pRsp->Sequence = pCmd->Sequence; |
| pRsp->CID = pCmd->CID; |
| pRsp->Status = Ack; |
| // Currently only sending buffer size. But we have 3 more reserved paramters. |
| // Note: Rsp structure only has space for 12 bytes of data ( 3 params). If we |
| // are going to use all 4 parameters, we need a buffer and memcpy. |
| pRsp->Length = 16; |
| |
| *(UINT16_T *)&pRsp->Data[0] = COMM_PROTOCOL_BUFFER_SIZE & 0xffff; |
| *(UINT16_T *)&pRsp->Data[2] = (COMM_PROTOCOL_BUFFER_SIZE & 0xffff0000)>> 16; |
| pRsp->Flags = pRsp->Flags & ~(MESSAGE_FLAG); |
| pRsp->Flags = pRsp->Flags | getProtocolMsg()->MessageFlag; |
| |
| // This should be |
| // SendResponse(&pRsp->Command, 6 + pRsp->Length); |
| // See note above |
| SendResponse(&pRsp->Command, 6 + pRsp->Length); |
| return Retval; |
| } |
| |
| UINT_T HandleGetCrcCmd() |
| { |
| UINT_T Retval = 0; |
| pProtocolRsp pRsp = (pProtocolRsp)transmitBuff; |
| pProtocolCmd pCmd; |
| UINT_T BufferAddr; |
| INT_T BufferLen = 4; //Nack |
| |
| pCmd = getProtocolCmd(); |
| |
| pRsp->Command = pCmd->Command; |
| pRsp->Sequence = pCmd->Sequence; |
| pRsp->CID = pCmd->CID; |
| Retval = GetImageReadBackCrcBuffer(&BufferAddr, &BufferLen); |
| |
| pRsp->Flags = pRsp->Flags & ~(MESSAGE_FLAG); |
| pRsp->Flags = pRsp->Flags | getProtocolMsg()->MessageFlag; |
| |
| if(Retval == NoError){ |
| pRsp->Status = Ack; |
| //pRsp->Length is UINT8, BufferLen exceed 255 |
| pRsp->Length = BufferLen; |
| memcpy(&pRsp->Data[0], (UINT8 *)BufferAddr, BufferLen); |
| }else{ |
| pRsp->Status = Nack; |
| pRsp->Length = 4; |
| *(UINT16_T *)&pRsp->Data[0] = Retval & 0xffff; |
| *(UINT16_T *)&pRsp->Data[2] = (Retval & 0xffff0000)>> 16; |
| } |
| |
| //pRsp->Length is UINT8, BufferLen exceed 255, use BufferLen instead |
| SendResponse(&pRsp->Command, 6 + BufferLen); |
| return Retval; |
| } |
| |
| UINT_T HandleGetBadBlock() |
| { |
| UINT_T Retval = 0; |
| pProtocolRsp pRsp = (pProtocolRsp)transmitBuff; |
| pProtocolCmd pCmd; |
| P_FlashProperties_T pFlashProp = GetFlashProperties(BOOT_FLASH); |
| pBadBlockData bbData; |
| |
| pCmd = getProtocolCmd(); |
| |
| pRsp->Command = pCmd->Command; |
| pRsp->Sequence = pCmd->Sequence; |
| pRsp->CID = pCmd->CID; |
| pRsp->Status = Ack; |
| |
| bbData = (pBadBlockData)(&pRsp->Data[0]); |
| bbData->TotalBadBlocks = GetBadBlockNum(); |
| bbData->TotalBlocks = pFlashProp->NumBlocks; |
| pRsp->Length = 8; |
| |
| pRsp->Flags = pRsp->Flags & ~(MESSAGE_FLAG); |
| pRsp->Flags = pRsp->Flags | getProtocolMsg()->MessageFlag; |
| |
| SendResponse(&pRsp->Command, 6 + pRsp->Length); |
| return Retval; |
| } |
| |
| UINT_T AddMessageError(UINT_T ReportType, UINT_T ReportCode) |
| { |
| UINT_T Retval = 0; |
| |
| #if VERBOSE_MODE |
| UINT_T mIndex, i; |
| pProtocolMsg pMsg = getProtocolMsg(); |
| MessageReport Report; |
| |
| if(pMsg->NumMessagesQueued == MAXNUMOFMESSAGES) |
| return MessageBufferFullError; //this is when message buffer is full |
| |
| //find the next open slot in the Queue |
| //It will be right after the last good message |
| //this is a circular queue, so we use the '%' operation |
| mIndex = (pMsg->CurrentMessageIndex + pMsg->NumMessagesQueued) % MAXNUMOFMESSAGES; |
| |
| Report.ReportType = ReportType; |
| Report.Reserved = 0; |
| |
| for (i = 0; i < 4; i++) |
| { |
| Report.ReportCode[i] = (ReportCode >> (8 * i)) & 0xff; |
| } |
| |
| // copy message to buffer |
| pMsg->Lengths[mIndex] = 6; |
| |
| pMsg->Messages[mIndex][0] = Report.ReportType; |
| pMsg->Messages[mIndex][1] = Report.Reserved; |
| |
| for (i = 0; i < 4; i++) |
| { |
| pMsg->Messages[mIndex][i + 2] = Report.ReportCode[i]; |
| } |
| |
| pMsg->MessageType[mIndex] = 1; // Message type 1 indicate report code |
| //set flag |
| pMsg->MessageFlag = MESSAGE_FLAG; |
| |
| pMsg->NumMessagesQueued++; |
| |
| #endif //endif VERBOSE_MODE |
| return NoError; |
| } |
| |
| void InitProtocol(void) |
| { |
| pProtocolMsg pMsg = getProtocolMsg(); |
| //pProtocolCmd pCMD = getProtocolCmd(); |
| pProtocolRsp pRsp = getProtocolRsp(); |
| pProtocolISR pISR = getProtocolISR(); |
| |
| memset(pMsg, 0, sizeof(ProtocolMsg)); |
| //memset(pCMD, 0, sizeof(ProtocolCmd)); |
| memset(pRsp, 0, sizeof(ProtocolRsp)); |
| memset(pISR, 0, sizeof(ProtocolISR)); |
| } |
| |
| |
| |
| /* |
| * HandleRequest() |
| * |
| * This is the main function of the protocol manager. It is the entry point |
| * to start a request over a port after an interrupt is received. The process |
| * for handling a request is as follows: |
| * |
| * 1) Get the preamble from the port and verify it |
| * 2) Get the first command packet from the port |
| * 3) Send back and ack with proper flag settings |
| * 4) Based on the command jump to the download flow or the JTAG flow |
| * 5) Complete the download or JTAG request and when complete disconnect |
| * 6) return status to the caller |
| * |
| * |
| */ |
| |
| UINT_T HandleRequest(UINT_T src_addr, UINT_T dest_addr, UINT_T max_size, UINT_T image_id) |
| { |
| UINT_T Retval = NoError; |
| pProtocolCmd pCmd = getProtocolCmd(); |
| |
| do |
| { |
| switch(pCmd->Command) |
| { |
| case GetVersionCmd: |
| //Retval = HandleDownloadFlow(dest_addr, image_id, max_size); |
| break; |
| |
| #if!BOOTROM |
| case UploadDataHeaderCmd: |
| Retval = HandleUploadFlow(src_addr); |
| if(Retval != NoError) |
| return Retval; |
| break; |
| #endif |
| case DisconnectCmd: |
| //if there was an issue with a download, then tool will try to disconnect |
| //handle the disconnect, but return an error since we couldn't do a download |
| //getProtocolISR()->CommandReceived = TRUE; // This hack is needed for optimization. Handledisconnect waits for a command again |
| Retval = HandleDisconnect(); |
| return Retval; |
| default: |
| //Retval.ErrorCode = SendError(0); |
| //Retval.ErrorCode = UnknownProtocolCmd; |
| break; |
| } |
| if(Retval != NoError) |
| break; |
| |
| }while(pCmd->Command != DoneCmd); |
| |
| if(pCmd->Command == DoneCmd) |
| HandleDoneCmd(); |
| else |
| Retval = SendError(0); |
| |
| return Retval; |
| } |
| |
| //-------------------------------------------------------- |
| // Utility routines |
| //-------------------------------------------------------- |
| |
| |
| |
| /* |
| * Verify that the Preamble matches |
| */ |
| UINT8_T PM_VerifyPreamble( UINT8_T *candidateString ) |
| { |
| //Compare the candidate preamble to the defined string |
| if( 0 == memcmp(candidateString, preambleString, sizeof(preambleString)) ) |
| { //MATCH |
| //return that all is good |
| return TRUE; |
| } |
| else |
| { //Bad String |
| return FALSE; |
| } |
| } |
| |
| /* |
| * Check to see if routine has timed out |
| */ |
| UINT8_T CheckProtocolTimeOut(UINT_T StartTime) |
| { |
| UINT_T WaitTime = 0; |
| UINT_T CurrentTime; |
| |
| CurrentTime = GetOSCR0(); |
| |
| WaitTime = OSCR0IntervalInSec(StartTime, CurrentTime); // measure wait time in sec |
| |
| if (WaitTime >= PROTOCOL_WAITTIME) |
| return (CheckProtocolTimeOutError); |
| else return NoError; |
| } |
| |