/***************************************************************************** * 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; }
/***************************************************************************** * FUNCTION: HostInterruptRegInit * * RETURNS: N/A * * PARAMS: * hostIntrMaskRegMask - The bit mask to be modified. * state - one of WF_EXINT_DISABLE, WF_EXINT_ENABLE where * Disable implies clearing the bits and enable sets the bits. * * * NOTES: Initializes the 8-bit Host Interrupt register on the MRF24WB0M with the * specified mask value either setting or clearing the mask register * as determined by the input parameter state. The process requires * 2 spi operations which are performed in a blocking fashion. The * function does not return until both spi operations have completed. *****************************************************************************/ static void HostInterruptRegInit(UINT8 hostIntrMaskRegMask, UINT8 state) { UINT8 hostIntMaskValue; /* Host Int Register is a status register where each bit indicates a specific event */ /* has occurred. In addition, writing a 1 to a bit location in this register clears */ /* the event. */ /* Host Int Mask Register is used to enable those events activated in Host Int Register */ /* to cause an interrupt to the host */ /* read current state of Host Interrupt Mask register */ hostIntMaskValue = Read8BitWFRegister(WF_HOST_MASK_REG); /* if caller is disabling a set of interrupts */ if (state == WF_INT_DISABLE) { /* zero out that set of interrupts in the interrupt mask copy */ hostIntMaskValue = (hostIntMaskValue & ~hostIntrMaskRegMask); } /* else caller is enabling a set of interrupts */ else { /* set to 1 that set of interrupts in the interrupt mask copy */ hostIntMaskValue = (hostIntMaskValue & ~hostIntrMaskRegMask) | hostIntrMaskRegMask; } /* write out new interrupt mask value */ Write8BitWFRegister(WF_HOST_MASK_REG, hostIntMaskValue); /* ensure that pending interrupts from those updated interrupts are cleared */ Write8BitWFRegister(WF_HOST_INTR_REG, hostIntrMaskRegMask); }
/***************************************************************************** * 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: 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(); } }
/* * 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; }
/* * 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(); } }