/***************************************************************************** * FUNCTION: ProcessInterruptServiceResult * * RETURNS: N/A * * PARAMS: * N/A * * * NOTES: Processes EXINT from MRF24W. Called by WFProcess(). *****************************************************************************/ static void ProcessInterruptServiceResult(void) { uint8_t hostIntRegValue; uint8_t hostIntMaskRegValue; uint8_t hostInt; /* read hostInt register to determine cause of interrupt */ hostIntRegValue = Read8BitWFRegister(WF_HOST_INTR_REG); // OR in the saved interrupts during the time when we were waiting for raw complete, set by WFEintHandler() hostIntRegValue |= g_HostIntSaved; // done with the saved interrupts, clear variable g_HostIntSaved = 0; hostIntMaskRegValue = Read8BitWFRegister(WF_HOST_MASK_REG); // AND the two registers together to determine which active, enabled interrupt has occurred hostInt = hostIntRegValue & hostIntMaskRegValue; // if received a level 2 interrupt (should not happen!) if((hostInt & WF_HOST_INT_MASK_INT2) == WF_HOST_INT_MASK_INT2) { /* read the 16 bit interrupt register */ /* CURRENTLY unhandled interrupt */ WF_ASSERT(false); WF_EintEnable(); } // else if got a FIFO 1 Threshold interrupt (Management Fifo) else if((hostInt & WF_HOST_INT_MASK_FIFO_1_THRESHOLD) == WF_HOST_INT_MASK_FIFO_1_THRESHOLD) { /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, WF_HOST_INT_MASK_FIFO_1_THRESHOLD); // notify MAC state machine that management message needs to be processed g_MgmtReadMsgReady = true; } // else if got a FIFO 0 Threshold Interrupt (Data Fifo) else if((hostInt & WF_HOST_INT_MASK_FIFO_0_THRESHOLD) == WF_HOST_INT_MASK_FIFO_0_THRESHOLD) { /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, WF_HOST_INT_MASK_FIFO_0_THRESHOLD); g_HostRAWDataPacketReceived = true; /* this global flag is used in MACGetHeader() to determine a received data packet */ } // else got a Host interrupt that we don't handle else if(hostInt) { /* unhandled interrupt */ /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, hostInt); WF_EintEnable(); } // we got a spurious interrupt (no bits set in register) else { /* spurious interrupt */ WF_EintEnable(); } }
/***************************************************************************** * FUNCTION: WFEintHandler * * RETURNS: N/A * * PARAMS: * N/A * * * NOTES: This function must be called once, each time an external interrupt * is received from the WiFi device. The WiFi Driver will schedule any * subsequent SPI communication to process the interrupt. * * IMPORTANT NOTE: This function, and functions that are called by this function * must NOT use local variables. The PIC18, or any other processor * that uses overlay memory will corrupt the logical stack within * overlay memory if the interrupt uses local variables. * If local variables are used within an interrupt routine the toolchain * cannot properly determine how not to overwrite local variables in * non-interrupt releated functions, specifically the function that was * interrupted. *****************************************************************************/ void WFEintHandler(void) { /*--------------------------------------------------------*/ /* if driver is waiting for a RAW Move Complete interrupt */ /*--------------------------------------------------------*/ if (RawMoveState.waitingForRawMoveCompleteInterrupt) { /* read hostInt register and hostIntMask register to determine cause of interrupt */ g_EintHostIntRegValue = Read8BitWFRegister(WF_HOST_INTR_REG); g_EintHostIntMaskRegValue = Read8BitWFRegister(WF_HOST_MASK_REG); // AND the two registers together to determine which active, enabled interrupt has occurred g_EintHostInt = g_EintHostIntRegValue & g_EintHostIntMaskRegValue; /* if a RAW0 or RAW1 interrupt occurred, signifying RAW Move completed */ if(g_EintHostInt & (WF_HOST_INT_MASK_RAW_0_INT_0 | WF_HOST_INT_MASK_RAW_1_INT_0)) { /* save the copy of the active interrupts */ RawMoveState.rawInterrupt = g_EintHostInt; RawMoveState.waitingForRawMoveCompleteInterrupt = FALSE; /* if no other interrupts occurred other than a RAW0 or RAW1 interrupt */ if((g_EintHostInt & ~(WF_HOST_INT_MASK_RAW_0_INT_0 | WF_HOST_INT_MASK_RAW_1_INT_0)) == 0u) { /* clear the RAW interrupts, re-enable interrupts, and exit */ Write8BitWFRegister(WF_HOST_INTR_REG, (WF_HOST_INT_MASK_RAW_0_INT_0 | WF_HOST_INT_MASK_RAW_1_INT_0)); WF_EintEnable(); return; } /* else we got a RAW0 or RAW1 interrupt, but, there is also at least one other interrupt present */ else { // save the other interrupts and clear them for now // keep interrupts disabled g_HostIntSaved |= (g_EintHostInt & ~(WF_HOST_INT_MASK_RAW_0_INT_0 | WF_HOST_INT_MASK_RAW_1_INT_0)); Write8BitWFRegister(WF_HOST_INTR_REG, g_EintHostInt); } } /*----------------------------------------------------------------------------------*/ /* else we did not get a RAW interrupt, but we did get at least one other interrupt */ /*----------------------------------------------------------------------------------*/ else { g_HostIntSaved |= g_EintHostInt; Write8BitWFRegister(WF_HOST_INTR_REG, g_EintHostInt); WF_EintEnable(); } } // Once we're in here, external interrupts have already been disabled so no need to call WF_EintDisable() in here /* notify state machine that an interrupt occurred */ g_ExIntNeedsServicing = TRUE; }
/* ********************************************************************************************************* * WF_RxDataReadPacket() * * Description : Reads all or part of an Rx data packet from MRF24WB0M memory to Host CPU memory. * * Argument(s) : p_rxData - pointer to where Rx data packet will be written * length - Number of bytes to read from MRF24WB0M memory * startIndex - start index within MRF24WB0M memory to start read from * * Return(s) : None * * Caller(s) : Application * * Notes: : None * ********************************************************************************************************* */ void WF_RxDataReadPacket(uint8_t *p_rxData, uint16_t length, uint16_t startIndex) { #if !defined(USE_WF_HOST_BUFFER) uint16_t byteCount; #endif WF_ASSERT(startIndex == 0); /* if application calls this function, and gHostRAWDataPacketReceived is not true, then error, because */ /* driver has not received a data packet. */ if (!g_HostRAWDataPacketReceived) { WF_ASSERT(false); } g_HostRAWDataPacketReceived = false; /* clear flag for next data packet */ /* Ensure the MRF24WB0M is awake (only applies if PS-Poll was enabled) */ EnsureWFisAwake(); #if !defined(USE_WF_HOST_BUFFER) /* when testing with MCHP stack the packet is already mounted */ /* Mount Read FIFO to RAW Rx window. Size of Rx data packet is returned */ byteCount = RawMountRxBuffer(); WF_ASSERT(byteCount > 0); #endif /* now that buffer mounted it is safe to reenable interrupts */ WF_EintEnable(); /* read the requested bytes into callers buffer */ RawRead(RAW_RX_ID, RAW_RX_DEST_ADD_INDEX + startIndex, length, p_rxData); }
/***************************************************************************** * FUNCTION: WFProcess * * RETURNS: None * * PARAMS: None * * NOTES: This function is called from WFProcess. It does the following: * 1) checks for and processes MRF24W external interrupt events * 2) checks for and processes received management messages from the MRF24W * 3) maintains the PS-Poll state (if applicable) * *****************************************************************************/ void WFProcess(void) { #if defined(__18CXX) static UINT16 len; #else UINT16 len; #endif //---------------------------------------------------------- // if there is a MRF24W External interrupt (EINT) to process //---------------------------------------------------------- if (g_ExIntNeedsServicing == TRUE) { g_ExIntNeedsServicing = FALSE; ProcessInterruptServiceResult(); } //---------------------------------------- // else if there is management msg to read //---------------------------------------- else if (g_MgmtReadMsgReady == TRUE) { RawGetMgmtRxBuffer(&len); // handle received managment message g_MgmtReadMsgReady = FALSE; ProcessMgmtRxMsg(); // reenable interrupts WF_EintEnable(); } }
/***************************************************************************** * FUNCTION: WFHardwareInit * * RETURNS: error code * * PARAMS: None * * NOTES: Initializes CPU Host hardware interfaces (SPI, External Interrupt). * Also resets the MRF24W. *****************************************************************************/ void WFHardwareInit(void) { UINT8 mask8; UINT16 mask16; g_MgmtReadMsgReady = FALSE; g_ExIntNeedsServicing = FALSE; RawMoveState.rawInterrupt = 0; RawMoveState.waitingForRawMoveCompleteInterrupt = FALSE; /* not waiting for RAW move complete */ /* needed for Microchip PICTail (chip enable active low) */ WF_SetCE_N(WF_LOW); /* set low to enable regulator */ /* initialize the SPI interface */ WF_SpiInit(); ResetPll(); // needed until PLL fix made in A2 silicon /* Reset the MRF24W (using SPI bus to write/read MRF24W registers */ ChipReset(); /* disable the interrupts gated by the 16-bit host int register */ HostInterrupt2RegInit(WF_HOST_2_INT_MASK_ALL_INT, (UINT16)WF_INT_DISABLE); /* disable the interrupts gated the by main 8-bit host int register */ HostInterruptRegInit(WF_HOST_INT_MASK_ALL_INT, WF_INT_DISABLE); /* Initialize the External Interrupt for the MRF24W allowing the MRF24W to interrupt */ /* the Host from this point forward. */ WF_EintInit(); WF_EintEnable(); /* enable the following MRF24W interrupts in the INT1 8-bit register */ mask8 = (WF_HOST_INT_MASK_FIFO_1_THRESHOLD | /* Mgmt Rx Msg interrupt */ WF_HOST_INT_MASK_FIFO_0_THRESHOLD | /* Data Rx Msg interrupt */ WF_HOST_INT_MASK_RAW_0_INT_0 | /* RAW0 Move Complete (Data Rx) interrupt */ WF_HOST_INT_MASK_RAW_1_INT_0 | /* RAW1 Move Complete (Data Tx) interrupt */ WF_HOST_INT_MASK_INT2); /* Interrupt 2 interrupt */ HostInterruptRegInit(mask8, WF_INT_ENABLE); /* enable the following MRF24W interrupts in the INT2 16-bit register */ mask16 = (WF_HOST_INT_MASK_RAW_2_INT_0 | /* RAW2 Move Complete (Mgmt Rx) interrupt */ WF_HOST_INT_MASK_RAW_3_INT_0 | /* RAW3 Move Complete (Mgmt Tx) interrupt */ WF_HOST_INT_MASK_RAW_4_INT_0 | /* RAW4 Move Complete (Scratch) interrupt */ WF_HOST_INT_MASK_RAW_5_INT_0 | /* RAW5 Move Complete (Scratch) interrupt */ WF_HOST_INT_MASK_MAIL_BOX_0_WRT); HostInterrupt2RegInit(mask16, WF_INT_ENABLE); /* Disable PS-Poll mode */ WFConfigureLowPowerMode(WF_LOW_POWER_MODE_OFF); }
/***************************************************************************** * FUNCTION: WFProcess * * RETURNS: None * * PARAMS: None * * NOTES: This function is called from WFProcess. It does the following: * 1) checks for and processes MRF24WB0M external interrupt events * 2) checks for and processes received management messages from the MRF24WB0M * 3) maintains the PS-Poll state (if applicable) * *****************************************************************************/ void WFProcess(void) { UINT16 len; //---------------------------------------------------------- // if there is a MRF24WB0M External interrupt (EINT) to process //---------------------------------------------------------- if (g_ExIntNeedsServicing == TRUE) { g_ExIntNeedsServicing = FALSE; ProcessInterruptServiceResult(); } //---------------------------------------- // else if there is management msg to read //---------------------------------------- else if (g_MgmtReadMsgReady == TRUE) { /* Ensure the MRF24WB0M is awake (only applies if PS-Poll was enabled) */ EnsureWFisAwake(); //----------------------------- // process management read //----------------------------- // if the Raw Rx buffer is available, or only has the scratch mounted, then mount it so // we can process received Mgmt message. Otherwise, stay in this state and keep checking // until we can mount the Raw Rx buffer and get the management message. Once the Raw Rx // is acquired, rx data packets are held off until we finish processing mgmt message. if ( RawGetMgmtRxBuffer(&len) ) { // handle received managment message g_MgmtReadMsgReady = FALSE; ProcessMgmtRxMsg(); // reenable interrupts WF_EintEnable(); } } //----------------------------------- // else no EINT or Mgmt Rx to process //----------------------------------- else { #if defined (WF_USE_POWER_SAVE_FUNCTIONS) /* if PS-Poll mode was enabled by application and was previously deactivated by WF driver */ if (WFisPsPollEnabled() && !WFIsPsPollActive() ) { /* reactivate PS-Poll mode on MRF24WB0M (allow MRF24WB0M to sleep) */ WFConfigureLowPowerMode(WF_LOW_POWER_MODE_ON); } #endif } }
/***************************************************************************** * FUNCTION: WaitForMgmtResponse * * RETURNS: None * * PARAMS: expectedSubtype -- The expected subtype of the mgmt response * freeAction -- FREE_MGMT_BUFFER or DO_NOT_FREE_MGMT_BUFFER * * NOTES: Called after sending a mgmt request. This function waits for a mgmt * response. The caller can optionally request the the management * response be freed immediately (by this function) or not freed. If not * freed the caller is responsible to free the response buffer. *****************************************************************************/ void WaitForMgmtResponse(UINT8 expectedSubtype, UINT8 freeAction) { tMgmtMsgRxHdr hdr; /* Wait until mgmt response is received */ while (gMgmtConfirmMsgReceived == FALSE) { WFProcess(); /* if received a data packet while waiting for mgmt packet */ if (g_HostRAWDataPacketReceived) { /* loop until stack has processed the received data message */ while (g_HostRAWDataPacketReceived) { StackTask(); } /* ensure interrupts enabled */ WF_EintEnable(); } } /* set this back to FALSE so the next mgmt send won't think he has a response before one is received */ gMgmtConfirmMsgReceived = FALSE; /* if the caller wants to delete the response immediately (doesn't need any data from it */ if (freeAction == FREE_MGMT_BUFFER) { /* read and verify result before freeing up buffer to ensure our message send was successful */ RawRead(RAW_RX_ID, 0, (UINT16)(sizeof(tMgmtMsgRxHdr)), (UINT8 *)&hdr); /* Mgmt response 'result' field should always indicate success. If this assert is hit the error codes are located */ /* WFApi.h. Search for WF_SUCCESS for the list of error codes. */ WF_ASSERT(hdr.result == WF_SUCCESS); /* mgmt response subtype had better match subtype we were expecting */ WF_ASSERT(hdr.subtype == expectedSubtype); /* free mgmt buffer */ DeallocateMgmtRxBuffer(); /* if there was a mounted data packet prior to the mgmt tx/rx transaction, then restore it */ if (RestoreRxData == TRUE) { RestoreRxData = FALSE; PopRawWindow(RAW_RX_ID); SetRawWindowState(RAW_RX_ID, WF_RAW_DATA_MOUNTED); } } }
/***************************************************************************** * FUNCTION: WFProcess * * RETURNS: None * * PARAMS: None * * NOTES: This function is called from WFProcess. It does the following: * 1) checks for and processes MRF24W external interrupt events * 2) checks for and processes received management messages from the MRF24W * 3) maintains the PS-Poll state (if applicable) * *****************************************************************************/ void WFProcess(void) { #if defined(__XC8) static uint16_t len; #else uint16_t len; #endif //---------------------------------------------------------- // if there is a MRF24W External interrupt (EINT) to process //---------------------------------------------------------- if (g_ExIntNeedsServicing == true) { g_ExIntNeedsServicing = false; ProcessInterruptServiceResult(); } //---------------------------------------- // else if there is management msg to read //---------------------------------------- else if (g_MgmtReadMsgReady == true) { //----------------------------- // process management read //----------------------------- // if the Raw Rx buffer is available, or only has the scratch mounted, then mount it so // we can process received Mgmt message. Otherwise, stay in this state and keep checking // until we can mount the Raw Rx buffer and get the management message. Once the Raw Rx // is acquired, rx data packets are held off until we finish processing mgmt message. if ( RawGetMgmtRxBuffer(&len) ) { // handle received managment message g_MgmtReadMsgReady = false; ProcessMgmtRxMsg(); // reenable interrupts WF_EintEnable(); } } }
/***************************************************************************** * FUNCTION: WFProcess * * RETURNS: None * * PARAMS: None * * NOTES: This function is called from WFProcess. It does the following: * 1) checks for and processes MRF24WB0M external interrupt events * 2) checks for and processes received management messages from the MRF24WB0M * 3) maintains the PS-Poll state (if applicable) * *****************************************************************************/ void WFProcess(void) { UINT16 len; //---------------------------------------------------------- // if there is a MRF24WB0M External interrupt (EINT) to process //---------------------------------------------------------- if (g_ExIntNeedsServicing == TRUE) { g_ExIntNeedsServicing = FALSE; ProcessInterruptServiceResult(); } //---------------------------------------- // else if there is management msg to read //---------------------------------------- else if (g_MgmtReadMsgReady == TRUE) { /* Ensure the MRF24WB0M is awake (only applies if PS-Poll was enabled) */ EnsureWFisAwake(); //----------------------------- // process management read //----------------------------- // if the Raw Rx buffer is available, or only has the scratch mounted, then mount it so // we can process received Mgmt message. Otherwise, stay in this state and keep checking // until we can mount the Raw Rx buffer and get the management message. Once the Raw Rx // is acquired, rx data packets are held off until we finish processing mgmt message. if ( RawGetMgmtRxBuffer(&len) ) { // handle received managment message g_MgmtReadMsgReady = FALSE; ProcessMgmtRxMsg(); // reenable interrupts WF_EintEnable(); } } }
/***************************************************************************** * FUNCTION: WFHardwareInit * * RETURNS: error code * * PARAMS: None * * NOTES: Initializes CPU Host hardware interfaces (SPI, External Interrupt). * Also resets the MRF24WB0M. *****************************************************************************/ void WFHardwareInit(void) { g_MgmtReadMsgReady = FALSE; g_ExIntNeedsServicing = FALSE; RawMoveState.rawInterrupt = 0; RawMoveState.waitingForRawMoveCompleteInterrupt = FALSE; /* not waiting for RAW move complete */ /* initialize the SPI interface */ WF_SpiInit(); /* Reset the MRF24WB0M (using SPI bus to write/read MRF24WB0M registers */ ChipReset(); /* disable the interrupts gated by the 16-bit host int register */ HostInterrupt2RegInit(WF_HOST_2_INT_MASK_ALL_INT, WF_INT_DISABLE); /* disable the interrupts gated the by main 8-bit host int register */ HostInterruptRegInit(WF_HOST_INT_MASK_ALL_INT, WF_INT_DISABLE); /* Initialize the External Interrupt for the MRF24WB0M allowing the MRF24WB0M to interrupt * the Host from this point forward. */ WF_EintInit(); WF_EintEnable(); /* enable the following MRF24WB0M interrupts */ HostInterruptRegInit((WF_HOST_INT_MASK_FIFO_1_THRESHOLD | /* Mgmt Rx Msg interrupt */ WF_HOST_INT_MASK_FIFO_0_THRESHOLD | /* Data Rx Msg interrupt */ WF_HOST_INT_MASK_RAW_0_INT_0 | /* RAW0 Move Complete interrupt */ WF_HOST_INT_MASK_RAW_1_INT_0), /* RAW1 Move Complete interrupt */ WF_INT_ENABLE); /* Disable PS-Poll mode */ WFConfigureLowPowerMode(WF_LOW_POWER_MODE_OFF); }
/******************************************************************************* Function: void WaitForMgmtResponse(UINT8 expectedSubtype, UINT8 freeAction) Summary: Waits for a management response Description: Called after sending a mgmt request. This function waits for a mgmt response. The caller can optionally request the the management response be freed immediately (by this function) or not freed. If not freed, the caller is responsible to free the response buffer. Precondition: MACInit must be called. Parameters: expectedSubtype -- Expected subtype of the mgmt response freeAction -- FREE_MGMT_BUFFER or DO_NOT_FREE_MGMT_BUFFER Returns: None Remarks: *****************************************************************************/ void WaitForMgmtResponse(UINT8 expectedSubtype, UINT8 freeAction) { #if defined(__18CXX) static tMgmtMsgRxHdr hdr; #else tMgmtMsgRxHdr hdr; #endif g_WaitingForMgmtResponse = TRUE; /* Wait until mgmt response is received */ while (gMgmtConfirmMsgReceived == FALSE) { WFProcess(); /* if received a data packet while waiting for mgmt packet */ if (g_HostRAWDataPacketReceived) { // We can't let the StackTask processs data messages that come in while waiting for mgmt // response because the application might send another mgmt message, which is illegal until the response // is received for the first mgmt msg. And, we can't prevent the race condition where a data message // comes in before a mgmt response is received. Thus, the only solution is to throw away a data message // that comes in while waiting for a mgmt response. This should happen very infrequently. If using TCP then the // stack takes care of retries. If using UDP, the application has to deal with occasional data messages not being // received. Also, applications typically do not send a lot of management messages after connected. // throw away the data rx RawMountRxBuffer(RAW_DATA_RX_ID); DeallocateDataRxBuffer(); g_HostRAWDataPacketReceived = FALSE; /* ensure interrupts enabled */ WF_EintEnable(); } } g_WaitingForMgmtResponse = FALSE; /* set this back to FALSE so the next mgmt send won't think he has a response before one is received */ gMgmtConfirmMsgReceived = FALSE; /* if the caller wants to delete the response immediately (doesn't need any data from it */ if (freeAction == FREE_MGMT_BUFFER) { /* read and verify result before freeing up buffer to ensure our message send was successful */ RawRead(RAW_MGMT_RX_ID, 0, (UINT16)(sizeof(tMgmtMsgRxHdr)), (UINT8 *)&hdr); /* mgmt response subtype had better match subtype we were expecting */ WF_ASSERT(hdr.subtype == expectedSubtype); /* Mgmt response 'result' field should always indicate success. If this assert is hit the error codes are located */ /* WFApi.h. Search for WF_SUCCESS for the list of error codes. */ if (hdr.result == WF_ERROR_HOST_SCAN_NOT_ALLOWED) { #if defined(STACK_USE_UART) putrsUART("Host Scan Failed. Host scan is allowed only in idle or connected state\r\n"); #endif } else if (hdr.result == WF_ERROR_INVALID_WPS_PIN) { #if defined(STACK_USE_UART) putrsUART("WPS failed : Invalid WPS PIN data\r\n"); #endif } else if (hdr.result == WF_ERROR_DISCONNECT_FAILED) { #if defined(STACK_USE_UART) putrsUART("Disconnect failed. Disconnect is allowed only when module is in connected state\r\n"); #endif } else if (hdr.result == WF_ERROR_NO_STORED_BSS_DESCRIPTOR) { #if defined(STACK_USE_UART) putrsUART("No stored scan results\r\n"); #endif } else if (hdr.result != WF_SUCCESS) { #if defined(STACK_USE_UART) UINT8 buf[8]; putrsUART("WaitForMgmtResponse result error: "); sprintf((char *)buf, "%d",hdr.result); putrsUART((char *)buf); putrsUART("\r\n"); #endif //WF_ASSERT(FALSE); } /* free mgmt buffer */ DeallocateMgmtRxBuffer(); } }
void IspSpiDMA_Rx(uint8_t *pbuf,uint16_t length) { bool intDisabled; unsigned char txTrash[3000]; // pbuf points to uint8_t array of data to be received from MRF // length indicates number of bytes to read intDisabled = WF_EintIsDisabled(); WF_EintDisable(); IEC1CLR=0x00030000; // disable DMA channel 0&1 interrupts IFS1CLR=0x00030000; // clear existing DMA channel 0&1 interrupt flag PLIB_DMA_Enable(0); // DMACONSET=0x00008000; // enable the DMA controller PLIB_DMA_ChannelXPrioritySelect(0,DMA_CHANNEL_0, DMA_CHANNEL_PRIORITY_3);//DCH0CONSET = 0x3; // channel off, pri 3, no chaining PLIB_DMA_ChannelXChainDisable(0,DMA_CHANNEL_0); PLIB_DMA_ChannelXPrioritySelect(0,DMA_CHANNEL_1, DMA_CHANNEL_PRIORITY_2);// DCH1CONSET = 0x03;//0x62; PLIB_DMA_ChannelXChainEnable(0,DMA_CHANNEL_1); DCH0ECONCLR=0xFFFFFFFF; // no start or stop irq?s, no pattern match DCH1ECONCLR=0xFFFFFFFF; // no start or stop irq?s, no pattern match // program the transfer PLIB_DMA_ChannelXSourceStartAddressSet (0,DMA_CHANNEL_0, ((unsigned long int)txTrash) & 0x1FFFFFFFL); PLIB_DMA_ChannelXDestinationStartAddressSet(0,DMA_CHANNEL_1, ((unsigned long int)pbuf) & 0x1FFFFFFFL); if( MRF24W_SPI_CHN == 1) { PLIB_DMA_ChannelXDestinationStartAddressSet(0,DMA_CHANNEL_0, ((unsigned long int)&SPI1BUF) & 0x1FFFFFFFL); PLIB_DMA_ChannelXSourceStartAddressSet (0,DMA_CHANNEL_1, ((unsigned long int)&SPI1BUF) & 0x1FFFFFFFL); } else if( MRF24W_SPI_CHN == 2) { PLIB_DMA_ChannelXDestinationStartAddressSet(0,DMA_CHANNEL_0, ((unsigned long int)&SPI2BUF) & 0x1FFFFFFFL); PLIB_DMA_ChannelXSourceStartAddressSet (0,DMA_CHANNEL_1, ((unsigned long int)&SPI2BUF) & 0x1FFFFFFFL); } PLIB_DMA_ChannelXSourceSizeSet (0,DMA_CHANNEL_0,length); PLIB_DMA_ChannelXDestinationSizeSet(0,DMA_CHANNEL_0,1 ); PLIB_DMA_ChannelXCellSizeSet (0,DMA_CHANNEL_0,1 ); PLIB_DMA_ChannelXSourceSizeSet (0,DMA_CHANNEL_1,1); PLIB_DMA_ChannelXDestinationSizeSet(0,DMA_CHANNEL_1,length); PLIB_DMA_ChannelXCellSizeSet (0,DMA_CHANNEL_1,1 ); DCH0INTCLR=0x00ff00ff; // clear existing events, disable all interrupts DCH1INTCLR=0x00ff00ff; // clear existing events, disable all interrupts // initiate a transfer PLIB_DMA_ChannelXStartIRQSet(0, DMA_CHANNEL_0, DMA_TRIGGER_SPI_1_TRANSMIT); PLIB_DMA_ChannelXTriggerEnable(0, DMA_CHANNEL_0, DMA_CHANNEL_TRIGGER_TRANSFER_START); PLIB_DMA_ChannelXStartIRQSet(0, DMA_CHANNEL_1, DMA_TRIGGER_SPI_1_RECEIVE); PLIB_DMA_ChannelXTriggerEnable(0, DMA_CHANNEL_1, DMA_CHANNEL_TRIGGER_TRANSFER_START); PLIB_DMA_ChannelXEnable(0,DMA_CHANNEL_0); PLIB_DMA_ChannelXEnable(0,DMA_CHANNEL_1); // DCH0ECONSET=0x00000080; // set CFORCE to 1 // do something else // poll to see that the transfer was done while(true) { register int pollCnt; // use a poll counter. // continuously polling the DMA controller in a tight // loop would affect the performance of the DMA transfer int dma0Flags=DCH0INT; int dma1Flags = DCH1INT; if((dma0Flags&0xb)&&(dma1Flags&0xb)) { // one of CHERIF (DCHxINT<0>), CHTAIF (DCHxINT<1>) // or CHBCIF (DCHxINT<3>) flags set break; // transfer completed } pollCnt=length<<1; // use an adjusted value here while(pollCnt--); // wait before reading again the DMA controller } PLIB_DMA_Disable(0); if(!intDisabled) { WF_EintEnable(); } }
/* * MRF24WG interrupt handler, called directly from the the interrupt routine, * _WFInterrupt() in wf_eint_stub.c. * * Must be called, once, for each MRF24WG interrupt. * * IMPORTANT: This function, and functions called from this function must not * use local variables, especially if the MCU uses overlay memory * like the Microchip PIC18 MCU. The logical stack is contained * within the overlay memory, and if the interrupt uses local variables * the toolchain cannot be relied on to not overwrite local variables * in non-interrupt functions, specifically the function that was * interrupted by this interrupt. */ void WF_EintHandler() { /*--------------------------------------------------------*/ /* if driver is waiting for a RAW Move Complete interrupt */ /*--------------------------------------------------------*/ if (isWaitingForRawMoveCompleteInterrupt()) { // read hostInt register and hostIntMask register to determine cause of interrupt // TODO: [NOTE: Stellaris requires two reads to get proper SPI read?] g_EintHostIntRegValue = Read8BitWFRegister(WF_HOST_INTR_REG); g_EintHostIntRegValue = Read8BitWFRegister(WF_HOST_INTR_REG); g_EintHostIntMaskRegValue = Read8BitWFRegister(WF_HOST_MASK_REG); // AND the two registers together to determine which active, enabled interrupt has occurred g_EintHostInt = g_EintHostIntRegValue & g_EintHostIntMaskRegValue; // If a Raw move complete interrupt occurred if (g_EintHostInt & (WF_HOST_INT_MASK_RAW_0_INT_0 | WF_HOST_INT_MASK_RAW_1_INT_0 | WF_HOST_INT_MASK_INT2)) { // Let the Raw driver know which interrupt occurred and clear the flag SignalRawInterruptEvent(g_EintHostInt); ClearWaitingForRawMoveCompleteInterrupt(); /* if no other interrupts occurred other than a RAW0/RAW1/RAW2/RAW3/RAW4 Raw Move Complete */ if ((g_EintHostInt & ~(WF_HOST_INT_MASK_RAW_0_INT_0 | WF_HOST_INT_MASK_RAW_1_INT_0 | WF_HOST_INT_MASK_INT2)) == 0) { /* clear the RAW interrupts, re-enable interrupts, and exit */ Write8BitWFRegister(WF_HOST_INTR_REG, (WF_HOST_INT_MASK_RAW_0_INT_0 | WF_HOST_INT_MASK_RAW_1_INT_0 | WF_HOST_INT_MASK_INT2)); Write16BitWFRegister(WF_HOST_INTR2_REG, (WF_HOST_INT_MASK_RAW_2_INT_0 | WF_HOST_INT_MASK_RAW_3_INT_0 | WF_HOST_INT_MASK_RAW_4_INT_0 | WF_HOST_INT_MASK_RAW_5_INT_0)); WF_EintEnable(); return; } /* else we got a RAW0/RAW1/RAW2/RAW3/RAW4/RAW5 Raw Move Complete interrupt, but, there is also at */ /* least one other interrupt present */ else { // save the other interrupts and clear them, along with the Raw Move Complete interrupts // keep interrupts disabled Write16BitWFRegister(WF_HOST_INTR2_REG, (WF_HOST_INT_MASK_RAW_2_INT_0 | WF_HOST_INT_MASK_RAW_3_INT_0 | WF_HOST_INT_MASK_RAW_4_INT_0 | WF_HOST_INT_MASK_RAW_5_INT_0)); g_HostIntSaved |= (g_EintHostInt & ~(WF_HOST_INT_MASK_RAW_0_INT_0 | WF_HOST_INT_MASK_RAW_1_INT_0 | WF_HOST_INT_MASK_INT2)); Write8BitWFRegister(WF_HOST_INTR_REG, g_EintHostInt); // leave interrupt disabled for now } } /*--------------------------------------------------------------------------------------------------*/ /* else we did not get a 'RAW Move Complete' interrupt, but we did get at least one other interrupt */ /*--------------------------------------------------------------------------------------------------*/ else { g_HostIntSaved |= g_EintHostInt; Write8BitWFRegister(WF_HOST_INTR_REG, g_EintHostInt); WF_EintEnable(); } } // used by InterruptCheck() g_ExIntNeedsServicing = true; }
/***************************************************************************** * FUNCTION: ProcessInterruptServiceResult * * RETURNS: N/A * * PARAMS: * N/A * * * NOTES: Processes EXINT from MRF24WB0M. Called by WFProcess(). *****************************************************************************/ static void ProcessInterruptServiceResult(void) { UINT8 hostIntRegValue; UINT8 hostIntMaskRegValue; UINT8 hostInt; /* Ensure the MRF24WB0M stays awake (only applies if PS-Poll was enabled) */ EnsureWFisAwake(); /* read hostInt register to determine cause of interrupt */ hostIntRegValue = Read8BitWFRegister(WF_HOST_INTR_REG); // OR in the saved interrupts during the time when we were waiting for raw complete, set by WFEintHandler() hostIntRegValue |= g_HostIntSaved; // done with the saved interrupts, clear variable g_HostIntSaved = 0; hostIntMaskRegValue = Read8BitWFRegister(WF_HOST_MASK_REG); // AND the two registers together to determine which active, enabled interrupt has occurred hostInt = hostIntRegValue & hostIntMaskRegValue; // if received a level 2 interrupt (should not happen!) if((hostInt & WF_HOST_INT_MASK_INT2) == WF_HOST_INT_MASK_INT2) { /* read the 16 bit interrupt register */ /* CURRENTLY unhandled interrupt */ WF_ASSERT(FALSE); WF_EintEnable(); } // else if got a FIFO 1 Threshold interrupt (Management Fifo) else if((hostInt & WF_HOST_INT_MASK_FIFO_1_THRESHOLD) == WF_HOST_INT_MASK_FIFO_1_THRESHOLD) { /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, WF_HOST_INT_MASK_FIFO_1_THRESHOLD); // notify MAC state machine that management message needs to be processed g_MgmtReadMsgReady = TRUE; } // else if got a FIFO 0 Threshold Interrupt (Data Fifo) else if((hostInt & WF_HOST_INT_MASK_FIFO_0_THRESHOLD) == WF_HOST_INT_MASK_FIFO_0_THRESHOLD) { /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, WF_HOST_INT_MASK_FIFO_0_THRESHOLD); g_HostRAWDataPacketReceived = TRUE; /* this global flag is used in MACGetHeader() to determine a received data packet */ #if defined(WF_USE_DATA_TX_RX_FUNCTIONS) { UINT16 rxDataPacketLength; /* determine length of packet and signal the rx data packet event */ rxDataPacketLength = Read16BitWFRegister(WF_HOST_RFIFO_BCNT0_REG) & 0x0fff; /* LS 12 bits are the data length */ WF_ProcessEvent(WF_EVENT_RX_PACKET_RECEIVED, rxDataPacketLength); } #endif } // else got a Host interrupt that we don't handle else if(hostInt) { /* unhandled interrupt */ /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, hostInt); WF_EintEnable(); } // we got a spurious interrupt (no bits set in register) else { /* spurious interrupt */ WF_EintEnable(); } }
/***************************************************************************** * FUNCTION: WaitForRawMoveComplete * * RETURNS: Number of bytes that were overlayed (not always applicable) * * PARAMS: * rawId - RAW ID * * NOTES: Waits for a RAW move to complete. *****************************************************************************/ static uint16_t WaitForRawMoveComplete(uint8_t rawId) { uint8_t rawIntMask; uint16_t byteCount; uint8_t regId; #if defined(WF_DEBUG) uint32_t startTickCount; uint32_t maxAllowedTicks; #endif /* create mask to check against for Raw Move complete interrupt for either RAW0 or RAW1 */ rawIntMask = (rawId == RAW_ID_0) ? WF_HOST_INT_MASK_RAW_0_INT_0:WF_HOST_INT_MASK_RAW_1_INT_0; /* These variables are shared with the ISR so need to be careful when setting them. the WFEintHandler() is the isr that will touch these variables but will only touch them if RawMoveState.waitingForRawMoveCompleteInterrupt is set to true. RawMoveState.waitingForRawMoveCompleteInterrupt is only set true here and only here. so as long as we set RawMoveState.rawInterrupt first and then set RawMoveState.waitingForRawMoveCompleteInterrupt to true, we are guranteed that the ISR won't touch RawMoveState.rawInterrupt and RawMoveState.waitingForRawMoveCompleteInterrupt. */ RawMoveState.rawInterrupt = 0; RawMoveState.waitingForRawMoveCompleteInterrupt = true; WF_EintEnable(); #if defined(WF_DEBUG) // Before we enter the while loop, get the tick timer count and save it maxAllowedTicks = TICKS_PER_SECOND / 2; /* 500 ms timeout */ startTickCount = (uint32_t)TickGet(); #endif while (1) { /* if received an external interrupt that signalled the RAW Move */ /* completed then break out of this loop */ if (RawMoveState.rawInterrupt & rawIntMask) { break; } #if defined(WF_DEBUG) /* If timed out waiting for RAW Move complete than lock up */ if (TickGet() - startTickCount >= maxAllowedTicks) { WF_ASSERT(false); } #endif } /* end while */ /* if interrupt was enabled by us here, we should disable it now that we're finished */ if (gIntDisabled) { WF_EintDisable(); } /* read the byte count and return it */ regId = (rawId == RAW_ID_0) ? WF_HOST_RAW0_CTRL1_REG:WF_HOST_RAW1_CTRL1_REG; byteCount = Read16BitWFRegister(regId); return ( byteCount ); }
/***************************************************************************** * FUNCTION: WFHardwareInit * * RETURNS: error code * * PARAMS: None * * NOTES: Initializes CPU Host hardware interfaces (SPI, External Interrupt). * Also resets the MRF24W. *****************************************************************************/ void WFHardwareInit(void) { UINT8 mask8; UINT16 mask16; g_MgmtReadMsgReady = FALSE; g_ExIntNeedsServicing = FALSE; RawMoveState.rawInterrupt = 0; RawMoveState.waitingForRawMoveCompleteInterrupt = FALSE; /* not waiting for RAW move complete */ /* initialize the SPI interface */ WF_SpiInit(); #if defined(__Digilent_Build__) WF_SetRST_N(WF_LOW); // put module into reset; should already be there. // we have taken out the next 3 lines as MarkW says we do not need to toggle HIB to competely reset the part. // WF_SetCE_N(WF_HIGH); // disable module, turn off regulators // DelayMs(200); // 200ms to allow decoupling caps to discharge, between the 70uF in the MRF , this can take some time. // WF_SetCE_N(WF_LOW); // enable module, turn on regulators; careful this has an inrush that can drag the Power supply below min. if the MRF is not decoupled well enough. DelayMs(2); // Spec says at least 1ms to let the regulators settle, leave this here to ensure timing from board powerup. WF_SetRST_N(WF_HIGH); // take module out of of reset DelayMs(5); // Per MarkW’s email, leave 5ms here before accessing the SPI port #else /* Toggle the module into and then out of hibernate */ WF_SetCE_N(WF_HIGH); /* disable module */ WF_SetCE_N(WF_LOW); /* enable module */ /* Toggle the module into and out of reset */ WF_SetRST_N(WF_LOW); // put module into reset WF_SetRST_N(WF_HIGH); // take module out of of reset #endif /* Silicon work-around -- needed for A1 silicon to initialize PLL values correctly */ ResetPll(); /* Soft reset the MRF24W (using SPI bus to write/read MRF24W registers */ ChipReset(); /* disable the interrupts gated by the 16-bit host int register */ HostInterrupt2RegInit(WF_HOST_2_INT_MASK_ALL_INT, (UINT16)WF_INT_DISABLE); /* disable the interrupts gated the by main 8-bit host int register */ HostInterruptRegInit(WF_HOST_INT_MASK_ALL_INT, WF_INT_DISABLE); /* Initialize the External Interrupt for the MRF24W allowing the MRF24W to interrupt */ /* the Host from this point forward. */ WF_EintInit(); WF_EintEnable(); /* enable the following MRF24W interrupts in the INT1 8-bit register */ mask8 = (WF_HOST_INT_MASK_FIFO_1_THRESHOLD | /* Mgmt Rx Msg interrupt */ WF_HOST_INT_MASK_FIFO_0_THRESHOLD | /* Data Rx Msg interrupt */ WF_HOST_INT_MASK_RAW_0_INT_0 | /* RAW0 Move Complete (Data Rx) interrupt */ WF_HOST_INT_MASK_RAW_1_INT_0 | /* RAW1 Move Complete (Data Tx) interrupt */ WF_HOST_INT_MASK_INT2); /* Interrupt 2 interrupt */ HostInterruptRegInit(mask8, WF_INT_ENABLE); /* enable the following MRF24W interrupts in the INT2 16-bit register */ mask16 = (WF_HOST_INT_MASK_RAW_2_INT_0 | /* RAW2 Move Complete (Mgmt Rx) interrupt */ WF_HOST_INT_MASK_RAW_3_INT_0 | /* RAW3 Move Complete (Mgmt Tx) interrupt */ WF_HOST_INT_MASK_RAW_4_INT_0 | /* RAW4 Move Complete (Scratch) interrupt */ WF_HOST_INT_MASK_RAW_5_INT_0 | /* RAW5 Move Complete (Scratch) interrupt */ WF_HOST_INT_MASK_MAIL_BOX_0_WRT); HostInterrupt2RegInit(mask16, WF_INT_ENABLE); /* Disable PS-Poll mode */ WFConfigureLowPowerMode(WF_LOW_POWER_MODE_OFF); }
/***************************************************************************** Function: uint16_t RawMove(uint16_t rawId, uint16_t srcDest, bool rawIsDestination, uint16_t size) Summary: Performs RAW Move operation Description: Raw Moves perform a variety of operations (e.g. allocating tx buffers, mounting rx buffers, copying from one raw window to another, etc.) Precondition: None Parameters: rawId -- Raw ID 0 thru 5, except is srcDest is RAW_COPY, in which case rawId contains the source address in the upper 4 bits and destination address in lower 4 bits. srcDest -- object that will either be the source or destination of the move: RAW_MAC RAW_MGMT_POOL RAW_DATA_POOL RAW_SCRATCH_POOL RAW_STACK_MEM RAW_COPY (this object not allowed, handled in RawToRawCopy() ) rawIsDestination -- true is srcDest is the destination, false if srcDest is the source of the move size -- number of bytes to overlay (not always applicable) Returns: Not always applicable, depending on the type of the raw move. When applicable, this function returns the number of bytes overlayed by the raw move. Remarks: None *****************************************************************************/ uint16_t RawMove(uint16_t rawId, uint16_t srcDest, bool rawIsDestination, uint16_t size) { uint16_t byteCount; uint8_t regId; uint8_t regValue; uint16_t ctrlVal = 0; bool intDisabled; // save current state of External interrupt and disable it intDisabled = WF_isEintDisabled(); WF_EintDisable(); /* These variables are shared with the ISR so need to be careful when setting them. the WF_EintHandler() is the isr that will touch these variables but will only touch them if RawMoveState.waitingForRawMoveCompleteInterrupt is set to TRUE. RawMoveState.waitingForRawMoveCompleteInterrupt is only set TRUE here and only here. so as long as we set RawMoveState.rawInterrupt first and then set RawMoveState.waitingForRawMoveCompleteInterrupt to TRUE, we are guaranteed that the ISR won't touch RawMoveState.rawInterrupt and RawMoveState.waitingForRawMoveCompleteInterrupt. */ RawMoveState.rawInterruptMask = 0; RawMoveState.waitingForRawMoveCompleteInterrupt = true; /* create control value that will be written to raw control register, which initiates the raw move */ if (rawIsDestination) { ctrlVal |= 0x8000; } /* fix later, simply need to ensure that size is 12 bits are less */ ctrlVal |= (srcDest << 8); /* defines are already shifted by 4 bits */ ctrlVal |= ((size >> 8) & 0x0f) << 8; /* MS 4 bits of size (bits 11:8) */ ctrlVal |= (size & 0x00ff); /* LS 8 bits of size (bits 7:0) */ /*---------------------------------------------------------------------------------------*/ /* this next 'if' block is used to ensure the expected raw interrupt signifying raw move */ /* complete is cleared */ /*---------------------------------------------------------------------------------------*/ /* if doing a raw move on Raw 0 or 1 (data rx or data tx) */ if (rawId <= RAW_ID_1) { /* Clear the interrupt bit in the host interrupt register (Raw 0 and 1 are in 8-bit host intr reg) */ regValue = (uint8_t)g_RawIntMask[rawId]; Write8BitWFRegister(WF_HOST_INTR_REG, regValue); } /* else doing raw move on mgmt rx, mgmt tx, or scratch */ else { /* Clear the interrupt bit in the host interrupt 2 register (Raw 2,3, and 4 are in 16-bit host intr2 reg */ regValue = g_RawIntMask[rawId]; Write16BitWFRegister(WF_HOST_INTR2_REG, regValue); } /*------------------------------------------------------------------------------------------------*/ /* now that the expected raw move complete interrupt has been cleared and we are ready to receive */ /* it, initiate the raw move operation by writing to the appropriate RawCtrl0. */ /*------------------------------------------------------------------------------------------------*/ regId = g_RawCtrl0Reg[rawId]; /* get RawCtrl0 register address for desired raw ID */ Write16BitWFRegister(regId, ctrlVal); /* write ctrl value to register */ // enable interrupts so we get raw move complete interrupt WF_EintEnable(); byteCount = WaitForRawMoveComplete(rawId); /* wait for raw move to complete */ // if interrupts were disabled coming into this function, put back to that state if (intDisabled) { WF_EintDisable(); } /* byte count is not valid for all raw move operations */ return byteCount; }
/* * Periodically called to check if the MRF24WG external interrupt occurred, and * completes the interrupt processing. * * Some processing takes place in the actual interrupt routine, and some processing * takes place later in the round robin. This function checks if an interrupt * has occurred, and if so, performs the rest of the interrupt processing. */ void InterruptCheck() { uint8_t hostIntRegValue; uint8_t hostIntMaskRegValue; uint8_t hostInt; uint16_t hostInt2; uint32_t assertInfo; // in no interrupt to process if (!g_ExIntNeedsServicing) { return; } g_ExIntNeedsServicing = false; /* read hostInt register to determine cause of interrupt */ hostIntRegValue = Read8BitWFRegister(WF_HOST_INTR_REG); // OR in the saved interrupts during the time when we were waiting for raw complete, set by WFEintHandler() hostIntRegValue |= g_HostIntSaved; // done with the saved interrupts, clear variable g_HostIntSaved = 0; hostIntMaskRegValue = Read8BitWFRegister(WF_HOST_MASK_REG); // AND the two registers together to determine which active, enabled interrupt has occurred hostInt = hostIntRegValue & hostIntMaskRegValue; // if received a level 2 interrupt if ((hostInt & WF_HOST_INT_MASK_INT2) == WF_HOST_INT_MASK_INT2) { // Either a mgmt tx or mgmt rx Raw move complete occurred, which is how // this interrupt is normally used. If this is the case, the event was // already handled in WF_EintHandler(), and all we need to do here is // clear the interrupt. However, there is one other event to check for; // this interrupt is also used by the MRF24WG to signal that it has // hit an assert condition. So, we check for that here. // if the MRF24WG has hit an assert condition hostInt2 = Read16BitWFRegister(WF_HOST_INTR2_REG); if (hostInt2 & WF_HOST_INT_MASK_MAIL_BOX_0_WRT) { // module number in upper 8 bits, assert information in lower 20 bits assertInfo = (((uint32_t)Read16BitWFRegister(WF_HOST_MAIL_BOX_0_MSW_REG)) << 16) | Read16BitWFRegister(WF_HOST_MAIL_BOX_0_LSW_REG); // signal this event EventEnqueue(WF_EVENT_MRF24WG_MODULE_ASSERT, assertInfo); } /* clear this interrupt */ Write16BitWFRegister(WF_HOST_INTR2_REG, WF_HOST_INT_MASK_INT2); } /* else if got a FIFO 1 Threshold interrupt (Management Fifo). Mgmt Rx msg ready to proces. */ else if ((hostInt & WF_HOST_INT_MASK_FIFO_1_THRESHOLD) == WF_HOST_INT_MASK_FIFO_1_THRESHOLD) { /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, WF_HOST_INT_MASK_FIFO_1_THRESHOLD); // signal that a mgmt msg, either confirm or indicate, has been received // and needs to be processed SignalMgmtMsgRx(); } /* else if got a FIFO 0 Threshold Interrupt (Data Fifo). Data Rx msg ready to process. */ else if ((hostInt & WF_HOST_INT_MASK_FIFO_0_THRESHOLD) == WF_HOST_INT_MASK_FIFO_0_THRESHOLD) { /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, WF_HOST_INT_MASK_FIFO_0_THRESHOLD); // signal that a data msg has been received and needs to be processed SignalPacketRx(); } /* else got a Host interrupt that we don't handle */ else if (hostInt) { /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, hostInt); WF_EintEnable(); } /* we got a spurious interrupt (no bits set in register) */ else { /* spurious interrupt */ WF_EintEnable(); } }
/***************************************************************************** * FUNCTION: WaitForRawMoveComplete * * RETURNS: Number of bytes that were overlayed (not always applicable) * * PARAMS: * rawId - RAW ID * * NOTES: Waits for a RAW move to complete. *****************************************************************************/ static uint16_t WaitForRawMoveComplete(uint8_t rawId) { uint8_t rawIntMask; uint16_t byteCount; uint8_t regId; bool intDisabled; #if defined(SYS_DEBUG_ENABLE) SYS_TICK startTickCount; SYS_TICK maxAllowedTicks; #endif /* create mask to check against for Raw Move complete interrupt for either RAW0 or RAW1 */ rawIntMask = (rawId == RAW_ID_0)?WF_HOST_INT_MASK_RAW_0_INT_0:WF_HOST_INT_MASK_RAW_1_INT_0; /* These variables are shared with the ISR so need to be careful when setting them. the WFEintHandler() is the isr that will touch these variables but will only touch them if RawMoveState.waitingForRawMoveCompleteInterrupt is set to true. RawMoveState.waitingForRawMoveCompleteInterrupt is only set true here and only here. so as long as we set RawMoveState.rawInterrupt first and then set RawMoveState.waitingForRawMoveCompleteInterrupt to true, we are guranteed that the ISR won't touch RawMoveState.rawInterrupt and RawMoveState.waitingForRawMoveCompleteInterrupt. */ RawMoveState.rawInterrupt = 0; RawMoveState.waitingForRawMoveCompleteInterrupt = true; // save state of external interrupt here intDisabled = WF_EintIsDisabled(); // if external interrupt is disabled, enable it because we need it for the while(1) loop to exit if(intDisabled) { WF_EintEnable(); } else if(WF_EintIsPending()) { WF_EintEnable(); } #if defined(SYS_DEBUG_ENABLE) // Before we enter the while loop, get the tick timer count and save it maxAllowedTicks = SYS_TICK_TicksPerSecondGet() / 2; /* 500 ms timeout */ startTickCount = SYS_TICK_Get(); #endif while (1) { /* if received an external interrupt that signalled the RAW Move */ /* completed then break out of this loop */ if(RawMoveState.rawInterrupt & rawIntMask) { break; } #if defined(SYS_DEBUG_ENABLE) /* If timed out waiting for RAW Move complete than lock up */ #if defined (__C30__) uint32_t x = 0; T2CON &= 0x7FFF; // Temporary Workaround for 16 bit device Timer23 read issue x = SYS_TICK_Get(); T2CON |= 0x8000; if ((x - startTickCount) >= maxAllowedTicks) { SYS_ASSERT(false, ""); } #else if (SYS_TICK_Get() - startTickCount >= maxAllowedTicks) { SYS_ASSERT(false, ""); } #endif #endif } /* end while */ /* if interrupt was enabled by us here, we should disable it now that we're finished */ if(intDisabled) { WF_EintDisable(); } /* read the byte count and return it */ regId = (rawId == RAW_ID_0)?WF_HOST_RAW0_CTRL1_REG:WF_HOST_RAW1_CTRL1_REG; byteCount = Read16BitWFRegister(regId); return ( byteCount ); }
/***************************************************************************** * FUNCTION: ProcessInterruptServiceResult * * RETURNS: N/A * * PARAMS: * N/A * * * NOTES: Processes EXINT from MRF24W. Called by WFProcess(). *****************************************************************************/ static void ProcessInterruptServiceResult(void) { UINT8 hostIntRegValue; UINT8 hostIntMaskRegValue; UINT8 hostInt; /* read hostInt register to determine cause of interrupt */ hostIntRegValue = Read8BitWFRegister(WF_HOST_INTR_REG); // OR in the saved interrupts during the time when we were waiting for raw complete, set by WFEintHandler() hostIntRegValue |= g_HostIntSaved; // done with the saved interrupts, clear variable g_HostIntSaved = 0; hostIntMaskRegValue = Read8BitWFRegister(WF_HOST_MASK_REG); // AND the two registers together to determine which active, enabled interrupt has occurred hostInt = hostIntRegValue & hostIntMaskRegValue; /* if received a level 2 interrupt (either a mgmt tx or mgmt rx Raw move complete occurred */ if((hostInt & WF_HOST_INT_MASK_INT2) == WF_HOST_INT_MASK_INT2) { UINT16 hostInt2; hostInt2 = Read16BitWFRegister(WF_HOST_INTR2_REG); if (hostInt2 & WF_HOST_INT_MASK_MAIL_BOX_0_WRT) { // the MRF24WG module CPU has hit an assert condition // display the assert info and do a WF_ASSERT #if defined(MRF24WG) WF_DisplayModuleAssertInfo(); #endif WF_ASSERT(FALSE); } WF_ASSERT(FALSE); /* This should not happen. Other than the module assert, this interrupt is only used to */ /* signify RAW Move Complete for RAW2/3/4. This event should be cleared in EintHandler(). */ /* clear this interrupt */ Write16BitWFRegister(WF_HOST_INTR2_REG, WF_HOST_INT_MASK_INT2); } /* else if got a FIFO 1 Threshold interrupt (Management Fifo). Mgmt Rx msg ready to proces. */ else if((hostInt & WF_HOST_INT_MASK_FIFO_1_THRESHOLD) == WF_HOST_INT_MASK_FIFO_1_THRESHOLD) { /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, WF_HOST_INT_MASK_FIFO_1_THRESHOLD); // notify MAC state machine that management message needs to be processed g_MgmtReadMsgReady = TRUE; } /* else if got a FIFO 0 Threshold Interrupt (Data Fifo). Data Rx msg ready to process. */ else if((hostInt & WF_HOST_INT_MASK_FIFO_0_THRESHOLD) == WF_HOST_INT_MASK_FIFO_0_THRESHOLD) { /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, WF_HOST_INT_MASK_FIFO_0_THRESHOLD); /* notify MAC state machine that data message needs to be processed */ g_HostRAWDataPacketReceived = TRUE; } /* else got a Host interrupt that we don't handle */ else if(hostInt) { /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, hostInt); WF_EintEnable(); } /* we got a spurious interrupt (no bits set in register) */ else { /* spurious interrupt */ WF_EintEnable(); } }
/***************************************************************************** * FUNCTION: WaitForRawMoveComplete * * RETURNS: Number of bytes that were overlayed (not always applicable) * * PARAMS: * rawId - RAW ID * * NOTES: Waits for a RAW move to complete. *****************************************************************************/ static UINT16 WaitForRawMoveComplete(UINT8 rawId) { UINT8 rawIntMask; UINT16 byteCount; UINT8 regId; BOOL intDisabled; #if defined(WF_DEBUG) UINT32 startTickCount; UINT32 maxAllowedTicks; #endif /* create mask to check against for Raw Move complete interrupt for either RAW0 or RAW1 */ if (rawId <= RAW_ID_1) { /* will be either raw 0 or raw 1 */ rawIntMask = (rawId == RAW_ID_0)?WF_HOST_INT_MASK_RAW_0_INT_0:WF_HOST_INT_MASK_RAW_1_INT_0; } else { /* will be INTR2 bit in host register, signifying RAW2, RAW3, or RAW4 */ rawIntMask = WF_HOST_INT_MASK_INT2; } /* These variables are shared with the ISR so need to be careful when setting them. the WFEintHandler() is the isr that will touch these variables but will only touch them if RawMoveState.waitingForRawMoveCompleteInterrupt is set to TRUE. RawMoveState.waitingForRawMoveCompleteInterrupt is only set TRUE here and only here. so as long as we set RawMoveState.rawInterrupt first and then set RawMoveState.waitingForRawMoveCompleteInterrupt to TRUE, we are guranteed that the ISR won't touch RawMoveState.rawInterrupt and RawMoveState.waitingForRawMoveCompleteInterrupt. */ RawMoveState.rawInterrupt = 0; RawMoveState.waitingForRawMoveCompleteInterrupt = TRUE; // save state of external interrupt here intDisabled = WF_EintIsDisabled(); // if external interrupt is disabled, enable it because we need it for the while(1) loop to exit if(intDisabled) { WF_EintEnable(); } else if(WF_EintIsPending()) { WF_EintEnable(); } #if defined(WF_DEBUG) // Before we enter the while loop, get the tick timer count and save it maxAllowedTicks = TICKS_PER_SECOND / 2; /* 500 ms timeout */ startTickCount = (UINT32)TickGet(); #endif while (1) { /* if received an external interrupt that signalled the RAW Move */ /* completed then break out of this loop */ if(RawMoveState.rawInterrupt & rawIntMask) { break; } #if defined(WF_DEBUG) /* If timed out waiting for RAW Move complete than lock up */ if (TickGet() - startTickCount >= maxAllowedTicks) { WF_ASSERT(FALSE); } #endif } /* end while */ /* if interrupt was enabled by us here, we should disable it now that we're finished */ if(intDisabled) { WF_EintDisable(); } /* read the byte count and return it */ regId = g_RawCtrl1Reg[rawId]; byteCount = Read16BitWFRegister(regId); return ( byteCount ); }
/***************************************************************************** * FUNCTION: WaitForMgmtResponse * * RETURNS: None * * PARAMS: expectedSubtype -- The expected subtype of the mgmt response * freeAction -- FREE_MGMT_BUFFER or DO_NOT_FREE_MGMT_BUFFER * * NOTES: Called after sending a mgmt request. This function waits for a mgmt * response. The caller can optionally request the the management * response be freed immediately (by this function) or not freed. If not * freed the caller is responsible to free the response buffer. *****************************************************************************/ void WaitForMgmtResponse(UINT8 expectedSubtype, UINT8 freeAction) { #if defined(__18CXX) static tMgmtMsgRxHdr hdr; #else tMgmtMsgRxHdr hdr; #endif g_WaitingForMgmtResponse = TRUE; /* Wait until mgmt response is received */ while (gMgmtConfirmMsgReceived == FALSE) { WFProcess(); /* if received a data packet while waiting for mgmt packet */ if (g_HostRAWDataPacketReceived) { // We can't let the StackTask processs data messages that come in while waiting for mgmt // response because the application might send another mgmt message, which is illegal until the response // is received for the first mgmt msg. And, we can't prevent the race condition where a data message // comes in before a mgmt response is received. Thus, the only solution is to throw away a data message // that comes in while waiting for a mgmt response. This should happen very infrequently. If using TCP then the // stack takes care of retries. If using UDP, the application has to deal with occasional data messages not being // received. Also, applications typically do not send a lot of management messages after connected. // throw away the data rx RawMountRxBuffer(); DeallocateDataRxBuffer(); g_HostRAWDataPacketReceived = FALSE; /* ensure interrupts enabled */ WF_EintEnable(); } } /* set this back to FALSE so the next mgmt send won't think he has a response before one is received */ gMgmtConfirmMsgReceived = FALSE; /* if the caller wants to delete the response immediately (doesn't need any data from it */ if (freeAction == FREE_MGMT_BUFFER) { /* read and verify result before freeing up buffer to ensure our message send was successful */ RawRead(RAW_RX_ID, 0, (UINT16)(sizeof(tMgmtMsgRxHdr)), (UINT8 *)&hdr); /* mgmt response subtype had better match subtype we were expecting */ WF_ASSERT(hdr.subtype == expectedSubtype); if (hdr.result == WF_ERROR_DISCONNECT_FAILED || hdr.result == WF_ERROR_NOT_CONNECTED) { #if defined(STACK_USE_UART) putrsUART("Disconnect failed. Disconnect is allowed only when module is in connected state\r\n"); #endif } else if (hdr.result == WF_ERROR_NO_STORED_BSS_DESCRIPTOR) { #if defined(STACK_USE_UART) putrsUART("No stored scan results\r\n"); #endif } else { WF_ASSERT(hdr.result == WF_SUCCESS); } /* free mgmt buffer */ DeallocateMgmtRxBuffer(); /* if there was a mounted data packet prior to the mgmt tx/rx transaction, then restore it */ if (RestoreRxData == TRUE) { RestoreRxData = FALSE; PopRawWindow(RAW_RX_ID); SetRawWindowState(RAW_RX_ID, WF_RAW_DATA_MOUNTED); } } }