📄 xnpm.nc
字号:
* NPX__ISP: * task to writes GROUP_ID and TOS_ID into eeprom, then invoke bootloader ****************************************************************************/task void NPX_ISP() {//setup parameters to pass//R20,R21 wProgId, R22:PageStart, R24,25:nwProgID uint16_t wPID; uint8_t cTemp; uint8_t *pAddr; cli(); //turnoff interrupts// Store GROUPID and LOCAL ADDRESS into EEPROM// note:this function blocks &waits until EEPROM is available eeprom_write_byte ((uint8_t *)AVREEPROM_GROUPID_ADDR, TOS_AM_GROUP); eeprom_write_byte ((uint8_t *)AVREEPROM_LOCALID_ADDR, TOS_LOCAL_ADDRESS);//lsbyte eeprom_write_byte ((uint8_t *)AVREEPROM_LOCALID_ADDR+1, (TOS_LOCAL_ADDRESS>>8));//msbyte //The following should really only be done when ISP has loaded the program... pAddr = &wProgramID; //the prog id eeprom_write_byte (AVREEPROM_PID_ADDR, *pAddr++);//lsbyte eeprom_write_byte (AVREEPROM_PID_ADDR+1, *pAddr);//msbyte while (!eeprom_is_ready()); //wait for eeprom to finish wPID = ~wProgramID; //inverted prog id __asm__ __volatile__ ("movw r20, %0" "\n\t"::"r" (wPID):"r20", "r21"); wPID = wEEProgStart; __asm__ __volatile__ ("movw r22, %0" "\n\t"::"r" (wPID):"r22", "r23"); wPID = wProgramID; //the prog id __asm__ __volatile__ ("movw r24, %0" "\n\t"::"r" (wPID):"r24", "r25");//call bootloader - it may never return... __asm__ __volatile__ ("call 0x1F800" "\n\t"::); //bootloader at 0xFC00 // __asm__ __volatile__ ("clr r1" "\n\t"::);//if here reboot/reprog failed bCommandOK= CMD_STATE_BADCHECKSUM; //default we don't recognize it if(bAckMessage) fNPXSendStatus(); return;} /*****************************************************************************TOS TASK Write specified buffer out to EEPROMOn completion, the CORRECT buffer FULL status will be cleared...Need a PENDING flag to keep trying until EEPROM ready or timeoutbELBuffAWE [0,1] points to 1 of 2 256 byte buffers in EEPROMwEE_LineW Absolute line# as starting address for written data. Actually modulo 16 because only 16 lines (16bytes/line * 16lines = 1page) are used. But wEE_LineW as an absolute line# is used elsewhere in the TestBenchELBUFF_NOFLINES Number of Lines (16bytes) to write.ELBuff Data buffer. Must be 16*ELBUFF_NOFLINES bytes deepWhen reach end of a Page Buffer (256bytes) we switch buffers for writingAnd then EEWRITE_LINEDONE handler will flush out the previous buffer to EEPROM'sinternal ROMNotes"1. hINSTANCE is a constant - should be variable set by StartEEPROM!!!!This is handled differently (correctly) in NESC !!!!*****************************************************************************/#define EEBufA 0 //Buffer IDs#define EEBufB 1 //Buffer IDstask void NPX_wEE_LineWrite() { uint8_t iRet; if( bEEWriteEnabled ) { if( !bEEPROMBusy){ //write the first of a 2line sequence bEELine1 = TRUE; // 1st line iRet = call EEPROMWrite.write(wEE_LineW, (uint8_t*)&ELBuff );// ADD RETRY TIMEOUT !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! if(!iRet) //failed post NPX_wEE_LineWrite(); //keep trying bEEPROMBusy= TRUE; //Handle variable number of line per buffer wEE_LineW++; //track absolute line number cLineinPage++; //next line within page if( cLineinPage >= NOFLINESPERPAGE ) { //at page boundary bELBuffAWE = !bELBuffAWE; //toggle line buffer for writing lines bELBuffFull = TRUE; //tells LineDone handler to flush internal buffer cLineinPage = 0; //reset line counter } } else //try again post NPX_wEE_LineWrite(); }}//tos-task/*****************************************************************************NPX_STATEMACHINEHandles various states during SREC Download.-On each SREC capsule received () writes srec line if EEPROM not busy, otherwise loops until ready.-SYS_DL_FAILCleansup / releases EEPROM resourceSend message to HostGoes into IDLE******************************************************************************/task void NPX_STATEMACHINE() { uint8_t cNextState; uint8_t bRePost; uint8_t bRet; uint16_t *wptr; cNextState = sSYSState; //default is no change bRePost = FALSE; //by default we do not repeat this statemachine task switch( sSYSState ) { case SYS_REQ_CIDMISSING: //get control back //if the requested PID does not match our current PID we ignore the request wptr = (uint16_t *)&(pNETTOSMsg->data[TS_PID]); if( *wptr != wProgramID ) { bCommandOK = CMD_STATE_BADSEQUENCE; cNextState = SYS_ACK; bRePost = TRUE; }else { cNextState = SYS_GET_CIDMISSING; //Release EEFLASH bRet = call EEPROMWrite.endWrite(); //EEWriteEndDone will invoke NPX statemachine if(bRet==FAIL) bRePost = TRUE; //endWrite will not signal enddone go directly to next state } break; case SYS_GET_CIDMISSING: sSYSMState = SYSM_UPDATE; fNPXGetNextEmptySREC(wCIDMissingPrevious);//this starts reading sequentially thru EEFLASH cNextState = sSYSState; break; case SYS_DL_START: cNextState = SYS_DL_START0; //this is a pseudo state waiting for APP to ack start dl request fNPXStartDownload(pNETTOSMsg); //prep & call app with DL request.Determines next state cNextState = sSYSState; //SYS state maybe changed by functioncall break; case SYS_DL_START1: //get system into clean known state cNextState = SYS_DL_START2; //Release EEFLASH unconditionally to get into clean state bRet = call EEPROMWrite.endWrite(); //EEWriteEndDone will invoke NPX statemachine if(bRet==FAIL) bRePost = TRUE; //no endWrite to signal enddone so go directly to START1 break; case SYS_DL_START2: // //Clear flags bEEWriteContinuous = FALSE; bEEWriteEnabled = FALSE; // eeprom writing enabled flag bEEPROMBusy = FALSE; //reset any pending eprom writes //lock down EEPROM resource bRet = call EEPROMWrite.startWrite(); //a function call - no event signal if( !bRet ) { //eeprom not available bCommandOK = CMD_STATE_BUSY; sSYSState = SYS_DL_FAIL; } else { bEEWriteContinuous = TRUE; //donot release EEFLASH after each srec write bEEWriteEnabled = TRUE; // eeprom writing enabled flag bEEPROMBusy = FALSE; //reset any pending eprom writes wEEProgStart = EE_PageW<<4;//the starting point in EEFlash wCapsuleNo = 0; //update current capsule# -Network capsule# starts at 1 //fNPXS0RecBuild(); //fNPXS0RecBuild sets up for EEFLASH write of S0 bCommandOK = CMD_STATE_DONE; sSYSMState = SYSM_DOWNLOAD; //Entered DOWNLOAD Major State cNextState = SYS_ACK; //we are ready to accept SREC Downloads } bRePost = TRUE; //goto next state break; case SYS_DL_SRECWRITE: //write SREC in DOWNLOAD Mode fNPXSRECStore(pNETTOSMsg); //storesrec cNextState = sSYSState; //whatever fNPXSRECStore did to sSYSState break; case SYS_UP_SRECWRITE: //write SREC in UPDATE Mode fNPXSRECUpdate(pNETTOSMsg); cNextState = sSYSState; //whatever fNPXSRECUpdate did to sSYSState break; case SYS_EEFLASH_WRITE: #ifdef PLATFORM_MICA2DOT call Leds.redOn(); #endif call Leds.yellowOn(); if( bEELineWritePending ){ //waiting to post a task to EEWrite if( !bEEPROMBusy ){ post NPX_wEE_LineWrite();//write buffer out to EEPROM bEELineWritePending = FALSE; } else //EEPROM is busy bRePost = TRUE; //re-execute NPX_STATEMACHINE only if busy }//writepending else { //not pending cNextState = SYS_EEFLASH_WRITEDONE; //nothing to so so endit bRePost = TRUE; } break; case SYS_EEFLASH_WRITEDONE: cNextState = SYS_ACK; //where we go next if( !bEEWriteContinuous ) { //release the resource after each write if( bEEWriteEnabled ) call EEPROMWrite.endWrite(); //EEWriteEndDone will invoke next state else bRePost = TRUE; //chain to next state } else bRePost = TRUE; //chain to next state call Leds.yellowOff(); //diagnostic break; case SYS_DL_END: //release EEPROM resource cNextState = SYS_DL_END_SIGNAL; if( bEEWriteEnabled ) call EEPROMWrite.endWrite(); //EEWriteEndDone will invoke NPX statemachine else bRePost = TRUE; break; case SYS_DL_END_SIGNAL: //signal application that download process is finished -good bCommandOK = CMD_STATE_DONE; wCapsuleNo = 0; //reset current Capsule# signal Xnp.NPX_DOWNLOAD_DONE(wProgramID,TRUE, EE_PageW); cNextState = SYS_ACK; sSYSMState = SYSM_IDLE; bRePost = TRUE; //re-execute NPX_STATEMACHINE break; case SYS_DL_FAIL: //release EEPROM resource if required cNextState = SYS_DL_FAIL_SIGNAL; if( bEEWriteEnabled ) call EEPROMWrite.endWrite(); //EEWriteEndDone will invoke NPX statemachine else bRePost = TRUE; break; case SYS_DL_FAIL_SIGNAL: if(bAckMessage) fNPXSendStatus(); sSYSMState = SYSM_IDLE; wCapsuleNo = 0; //reset current Capsule# //Tell client download has finished - badly signal Xnp.NPX_DOWNLOAD_DONE(wProgramID,FALSE, EE_PageW); cNextState = SYS_ACK; // should wait for EEPROM flush buffer to fini? bRePost = TRUE; //re-execute NPX_STATEMACHINE break; case SYS_IDLE_RENTRY: //resume idle conditions cNextState = SYS_IDLE; bNXPMsgBusy = FALSE; //call Leds.greenOn(); break; case SYS_IDLE: bNXPMsgBusy = FALSE; break; case SYS_ISP_REQ: wptr = (uint16_t *)&(pNETTOSMsg->data[TS_PID]); wProgramID = *wptr++; EE_PageW = EE_PAGE_START; wEEProgStart = EE_PageW<<4;//the starting point in EEFlash //check EEFLASH Capsule #1 (2lines per capsule)to verify this programID is present wEE_LineR = wEEProgStart+2; //Capsule#0 is legacy/expansion-future bEELineReadPending = TRUE; //statemachine handles retries etc cNextState = SYS_ISP_REQ1; bRePost = TRUE; break; case SYS_ISP_REQ1: case SYS_GETNEXTCID: //have read 1st half of srec from FLASH if( bEELineReadPending ){ #ifdef PLATFORM_MICA2DOT call Leds.redOn(); //led off during read/missing capsule check, ON at end if ok #endif call Leds.yellowOn(); call EEPROMRead.read(wEE_LineR, (uint8_t*)&ELBuff ); } //if fail do what? - go idle? break; case SYS_ACK: //send ack to network if required and then go idle if(bAckMessage ) //acknowledge to network fNPXSendStatus(); bNXPMsgBusy = FALSE; call Leds.redOff(); //diagnostic cNextState = SYS_IDLE; break; case SYS_GETDONE: call Leds.yellowOff(); // sSYSMState = SYS_IDLE; //no ack and leaves LED ON cNextState = SYS_IDLE; bNXPMsgBusy = FALSE; break; case SYS_BEACON: // call Leds.redOn(); //diagnostic // fNPXSendStatus(); if( !bTOSMsgBusy ) fProcessMissingCapsule(wProgramID, wCapsuleNo); bRePost = TRUE; //re-execute NPX_STATEMACHINE // call Leds.redOff(); //diagnostic break; default: break; } //switch// update state sSYSState = cNextState; //this updates BEFORE any new tasks start if( bRePost ) post NPX_STATEMACHINE(); //try againreturn;}//TASK NXP Statemachine /***************************************************************************** receive() - message from newtork******************************************************************************/event TOS_MsgPtr ReceiveMsg.receive(TOS_MsgPtr msgptr) { int (*ptr)(); uint16_t *wptr; uint8_t cNextState; TOS_MsgPtr pPrevious;//Filter for correct GROUP_ID and MOTEID for GSK compatibility if (msgptr->group != TOS_AM_GROUP) return msgptr; if ((msgptr->addr != TOS_BCAST_ADDR) && (msgptr->addr != TOS_LOCAL_ADDRESS) )return msgptr; if (bTOSMsgBusy) return msgptr; if (bNXPMsgBusy) return msgptr; //call Leds.yellowOff(); call Leds.greenOff(); //leds off call Leds.redOn(); //diagnostic - turns off at exit of statemachine SYS_ACK bNXPMsgBusy = TRUE; pPrevious = pNETTOSMsg; //save ptr to previous buffer pNETTOSMsg = msgptr; //point to new buffer cNextState = sSYSState; //statemachine updates// -------LOCAL COMMANDS addressed to this specific node if( (msgptr->addr == TOS_LOCAL_ADDRESS) ) { cCommand = msgptr->data[TS_CMD]; //save the netprog command ID cSubCommand = msgptr->data[TS_SUBCMD]; //save the command ID bCommandOK= CMD_STATE_UKNOWN; //default we don't recognize it bBCASTMsg = FALSE; bAckMessage = TRUE; switch (cCommand) //was [4] { case CMD_RST: //REBOOT ptr = 0; ptr(); break; case CMD_DOWNLOAD_STATUS: bCommandOK= CMD_STATE_DONE; //status command req reqognized cNextState = SYS_ACK; break; case CMD_STATUS: //Get node status bCommandOK= CMD_STATE_DONE; //status command req reqognized cNextState = SYS_ACK; break; case CMD_START_DOWNLOAD: //Header info for a code download// fNPXStartDownload(pNETTOSMsg); cNextState = SYS_DL_START; break; case CMD_DOWNLOADING: if(sSYSMState==SYSM_DOWNLOAD) cNextState = SYS_DL_SRECWRITE; else if (sSYSMState == SYSM_UPDATE) cNextState = SYS_UP_SRECWRITE; else cNextState = SYS_ACK; //ignore break; case CMD_DOWNLOAD_COMPLETE: cNextState = SYS_DL_END; break; case CMD_ISP_EXEC: cNextState = SYS_ISP_REQ; break; case CMD_GET_CIDMISSING:// wptr = &(pNETTOSMsg->data[TS_PID]); //tests are done in statemachine// wProgramID = *wptr; cNextState = SYS_REQ_CIDMISSING; break; case CMD_GET_PIDSTATUS: fNPXGetProgramID(pNETTOSMsg); bNXPMsgBusy = FALSE; call Leds.redOff(); //diagnostic - turns off at exit break; default:// call Leds.yellowOn(); cNextState = SYS_ACK; break; //invalid command }//switch command sSYSState = cNextState; post NPX_STATEMACHINE(); //try again
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -