/******************************************************************************* Function: void WFConfigureLowPowerMode(uint8_t action) Summary: Driver function to configure PS Poll mode. Description: This function is only used by the driver, not the application. This function, other than at initialization, is only used when the application has enabled PS-Poll mode. This function is used to temporarily deactivate PS-Poll mode when there is mgmt or data message tx/rx and then, when message activity has ceased, to again activate PS-Poll mode. Precondition: MACInit must be called first. Parameters: action - Can be either: * WF_LOW_POWER_MODE_ON * WF_LOW_POWER_MODE_OFF Returns: None. Remarks: None. *****************************************************************************/ void WFConfigureLowPowerMode(uint8_t action) { uint16_t lowPowerStatusRegValue; /*-----------------------------------------*/ /* if activating PS-Poll mode on MRF24W */ /*-----------------------------------------*/ if (action == WF_LOW_POWER_MODE_ON) { SYS_CONSOLE_MESSAGE("EPS\r\n"); Write16BitWFRegister(WF_PSPOLL_H_REG, REG_ENABLE_LOW_POWER_MASK); g_psPollActive = true; } /*---------------------------------------------------------------------------------------------*/ /* else deactivating PS-Poll mode on MRF24W (taking it out of low-power mode and waking it up) */ /*---------------------------------------------------------------------------------------------*/ else /* action == WF_LOW_POWER_MODE_OFF */ { SYS_CONSOLE_MESSAGE("DPS\r\n"); Write16BitWFRegister(WF_PSPOLL_H_REG, REG_DISABLE_LOW_POWER_MASK); g_psPollActive = false; /* poll the response bit that indicates when the MRF24W has come out of low power mode */ do { /* set the index register to the register we wish to read */ Write16BitWFRegister(WF_INDEX_ADDR_REG, WF_LOW_POWER_STATUS_REG); lowPowerStatusRegValue = Read16BitWFRegister(WF_INDEX_DATA_REG); } while (lowPowerStatusRegValue & REG_ENABLE_LOW_POWER_MASK); } }
/***************************************************************************** * FUNCTION: HostInterrupt2RegInit * * RETURNS: N/A * * PARAMS: * hostIntrMaskRegMask - The bit mask to be modified. * state - One of WF_INT_DISABLE, WF_INT_ENABLE where * Disable implies clearing the bits and enable sets the bits. * * * NOTES: Initializes the 16-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. *****************************************************************************/ static void HostInterrupt2RegInit(UINT16 hostIntMaskRegMask, UINT8 state) { UINT16 int2MaskValue; /* 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 int2 mask reg */ int2MaskValue = Read16BitWFRegister(WF_HOST_INTR2_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 */ int2MaskValue &= ~hostIntMaskRegMask; } /* else caller is enabling a set of interrupts */ else { /* set to 1 that set of interrupts in the interrupt mask copy */ int2MaskValue |= hostIntMaskRegMask; } /* write out new interrupt mask value */ Write16BitWFRegister(WF_HOST_INTR2_MASK_REG, int2MaskValue); /* ensure that pending interrupts from those updated interrupts are cleared */ Write16BitWFRegister(WF_HOST_INTR2_REG, hostIntMaskRegMask); }
/******************************************************************************* Function: void WFConfigureLowPowerMode(UINT8 action) Summary: Driver function to configure PS Poll mode. Description: This function is only used by the driver, not the application. This function, other than at initialization, is only used when the application has enabled PS-Poll mode. This function is used to temporarily deactivate PS-Poll mode when there is mgmt or data message tx/rx and then, when message activity has ceased, to again activate PS-Poll mode. Precondition: MACInit must be called first. Parameters: action - Can be either: * WF_LOW_POWER_MODE_ON * WF_LOW_POWER_MODE_OFF Returns: None. Remarks: None. *****************************************************************************/ void WFConfigureLowPowerMode(UINT8 action) { UINT16 lowPowerStatusRegValue; /*-----------------------------------------*/ /* if activating PS-Poll mode on MRF24WB0M */ /*-----------------------------------------*/ if (action == WF_LOW_POWER_MODE_ON) { Write16BitWFRegister(WF_PSPOLL_H_REG, REG_ENABLE_LOW_POWER_MASK); g_psPollActive = TRUE; } /*---------------------------------------------------------------------------------------------*/ /* else deactivating PS-Poll mode on MRF24WB0M (taking it out of low-power mode and waking it up) */ /*---------------------------------------------------------------------------------------------*/ else /* action == WF_LOW_POWER_MODE_OFF */ { Write16BitWFRegister(WF_PSPOLL_H_REG, 0x00); g_psPollActive = FALSE; /* poll the response bit that indicates when the MRF24WB0M has come out of low power mode */ do { /* set the index register to the register we wish to read (kWFCOMRegLoPwrStatusReg) */ Write16BitWFRegister(WF_INDEX_ADDR_REG, WF_LOW_POWER_STATUS_REG); lowPowerStatusRegValue = Read16BitWFRegister(WF_INDEX_DATA_REG); } while (lowPowerStatusRegValue & REG_ENABLE_LOW_POWER_MASK); } }
/******************************************************************************* Function: void WFConfigureLowPowerMode(uint8_t action) Summary: Driver function to configure PS Poll mode. Description: This function is only used by the driver, not the application. This function, other than at initialization, is only used when the application has enabled PS-Poll mode. This function is used to temporarily deactivate PS-Poll mode when there is mgmt or data message tx/rx and then, when message activity has ceased, to again activate PS-Poll mode. Precondition: MACInit must be called first. Parameters: action - Can be either: * WF_LOW_POWER_MODE_ON * WF_LOW_POWER_MODE_OFF Returns: None. Remarks: None. *****************************************************************************/ void WFConfigureLowPowerMode(uint8_t action) { uint16_t lowPowerStatusRegValue; //------------------------------------- // if activating PS-Poll mode on MRF24W //------------------------------------- if (action == WF_LOW_POWER_MODE_ON) { // dbgprintf("Enable PS\n"); Write16BitWFRegister(WF_PSPOLL_H_REG, REG_ENABLE_LOW_POWER_MASK); } //--------------------------------------------------------------------------------------------- // else deactivating PS-Poll mode on MRF24W (taking it out of low-power mode and waking it up) //--------------------------------------------------------------------------------------------- else // action == WF_LOW_POWER_MODE_OFF { // dbgprintf("Disable PS\n"); Write16BitWFRegister(WF_PSPOLL_H_REG, REG_DISABLE_LOW_POWER_MASK); /* poll the response bit that indicates when the MRF24W has come out of low power mode */ do { // set the index register to the register we wish to read Write16BitWFRegister(WF_INDEX_ADDR_REG, WF_SCRATCHPAD_1_REG); // read register lowPowerStatusRegValue = Read16BitWFRegister(WF_INDEX_DATA_REG); } while (lowPowerStatusRegValue & REG_ENABLE_LOW_POWER_MASK); } }
void SendMgmtMsg(uint8_t *p_header, uint8_t headerLength, uint8_t *p_data, uint8_t dataLength) { if (DRV_WIFI_InHibernateMode()) { DRV_WIFI_UserEventSet(DRV_WIFI_EVENT_ERROR, DRV_WIFI_ERROR_IN_HIBERNATE_MODE, true); return; } WF_MGMTMSG_MUTEX_LOCK(); EnsureWFisAwake(); /* write out management header */ RawSetIndex(RAW_SCRATCH_ID, MGMT_TX_BASE); RawSetByte(RAW_SCRATCH_ID, p_header, headerLength); /* write out data (if any) */ if (dataLength > 0) { RawSetByte(RAW_SCRATCH_ID, p_data, dataLength); } /* Signal MRF24WG that mgmt message ready to process */ Write16BitWFRegister(WF_HOST_MAIL_BOX_0_MSW_REG, 0x0400); Write16BitWFRegister(WF_HOST_MAIL_BOX_0_LSW_REG, 0x0000); }
/***************************************************************************** * FUNCTION: ChipReset * * RETURNS: N/A * * PARAMS: * N/A * * * NOTES: Performs the necessary SPI operations to cause the MRF24WB0M to reset. * This function also implements a delay so that it will not return until * the WiFi device is ready to receive messages again. The delay time will * vary depending on the amount of code that must be loaded from serial * flash. *****************************************************************************/ static void ChipReset(void) { UINT16 value; UINT32 timeoutPeriod; UINT32 startTickCount; timeoutPeriod = TICKS_PER_SECOND; /* 1000 ms */ /* needed for Microchip PICTail (chip enable active low) */ WF_SetCE_N(WF_LOW); /* set low to enable regulator */ /* Configure reset pin */ WF_SetRST_N(WF_HIGH); /* Let SPI lines settle before first SPI transaction */ DelayMs(1); /* clear the power bit to disable low power mode on the MRF24WB0M */ Write16BitWFRegister(WF_PSPOLL_H_REG, 0x0000); /* Set HOST_RESET bit in register to put device in reset */ Write16BitWFRegister(WF_HOST_RESET_REG, Read16BitWFRegister(WF_HOST_RESET_REG) | WF_HOST_RESET_MASK); /* Clear HOST_RESET bit in register to take device out of reset */ Write16BitWFRegister(WF_HOST_RESET_REG, Read16BitWFRegister(WF_HOST_RESET_REG) & ~WF_HOST_RESET_MASK); /* after reset is started poll register to determine when HW reset has completed */ startTickCount = (UINT32)TickGet(); do { Write16BitWFRegister(WF_INDEX_ADDR_REG, WF_HW_STATUS_REG); value = Read16BitWFRegister(WF_INDEX_DATA_REG); if (TickGet() - startTickCount >= timeoutPeriod) { WF_ASSERT(FALSE); } } while ( (value & WF_HW_STATUS_NOT_IN_RESET_MASK) == 0); /* if SPI not connected will read all 1's */ WF_ASSERT(value != 0xffff); /* now that chip has come out of HW reset, poll the FIFO byte count register */ /* which will be set to a non-zero value when the MRF24WB0M initialization is */ /* complete. */ startTickCount = (UINT32)TickGet(); do { value = Read16BitWFRegister(WF_HOST_WFIFO_BCNT0_REG); if (TickGet() - startTickCount >= timeoutPeriod) { WF_ASSERT(FALSE); } } while (value == 0); }
/***************************************************************************** Function: void RawToRawCopy(UINT8 rawDestId, UINT8 rawSourceId, UINT16 length) Summary: Performs a data copy from one raw window to another. Description: There is an additional step needed before invoking RawMove(); need to write the source and destination values to ScratchPad0 register so that the information is there before the WiFi chip starts the copy operation. Precondition: None Parameters: rawDestId -- RAW ID that is the destination of copy rawSourceId -- RAW ID that is the source of copy length -- number of bytes to copy from source to destination Returns: None Remarks: None *****************************************************************************/ void RawToRawCopy(UINT8 rawDestId, UINT8 rawSourceId, UINT16 length) { /* write source and destination address to scratchpad 0 register. The WiFi firmware */ /* will get these values when it starts processing the raw move operation and */ /* determines a raw copy operation is taking place. */ Write16BitWFRegister(WF_INDEX_ADDR_REG, WF_SCRATCHPAD_0_REG); Write16BitWFRegister(WF_INDEX_DATA_REG, (((UINT16)rawSourceId << 8) | (UINT16)rawDestId)); /* always perform the actual move on RAW 0, the firmware will check the scratchpad register */ /* for the actual source and destination */ RawMove(RAW_ID_0, RAW_COPY, TRUE, length); }
/***************************************************************************** Function: UINT16 RawMove(UINT16 rawId, UINT16 srcDest, BOOL rawIsDestination, UINT16 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 *****************************************************************************/ static UINT16 RawMove(UINT16 rawId, UINT16 srcDest, BOOL rawIsDestination, UINT16 size) { UINT16 byteCount; UINT8 regId; UINT8 regValue; UINT16 ctrlVal = 0; /* 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)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 */ byteCount = WaitForRawMoveComplete(rawId); /* wait for raw move to complete */ /* byte count is not valid for all raw move operations */ return byteCount; }
/***************************************************************************** * FUNCTION: ChipReset * * RETURNS: N/A * * PARAMS: * N/A * * * NOTES: Performs the necessary SPI operations to cause the MRF24W to do a soft * reset. * * This function waits for the MRF24WG to complete its initialization before * returning to the caller. The largest part of the wait is for the MRF24WG * to download any patch code in FLASH into its RAM. *****************************************************************************/ static void ChipReset(void) { UINT16 value; UINT32 timeoutPeriod; UINT32 startTickCount; /* clear the power bit to disable low power mode on the MRF24W */ Write16BitWFRegister(WF_PSPOLL_H_REG, 0x0000); /* Set HOST_RESET bit in register to put device in reset */ Write16BitWFRegister(WF_HOST_RESET_REG, Read16BitWFRegister(WF_HOST_RESET_REG) | WF_HOST_RESET_MASK); /* Clear HOST_RESET bit in register to take device out of reset */ Write16BitWFRegister(WF_HOST_RESET_REG, Read16BitWFRegister(WF_HOST_RESET_REG) & ~WF_HOST_RESET_MASK); /* after reset is started poll register to determine when HW reset has completed */ timeoutPeriod = TICKS_PER_SECOND * 3; /* 3000 ms */ startTickCount = (UINT32)TickGet(); do { Write16BitWFRegister(WF_INDEX_ADDR_REG, WF_HW_STATUS_REG); value = Read16BitWFRegister(WF_INDEX_DATA_REG); if (TickGet() - startTickCount >= timeoutPeriod) { WF_ASSERT(FALSE); } } while ( (value & WF_HW_STATUS_NOT_IN_RESET_MASK) == 0); /* if SPI not connected will read all 1's */ WF_ASSERT(value != 0xffff); /* now that chip has come out of HW reset, poll the FIFO byte count register */ /* which will be set to a non-zero value when the MRF24W initialization is */ /* complete. */ startTickCount = (UINT32)TickGet(); do { value = Read16BitWFRegister(WF_HOST_WFIFO_BCNT0_REG); if (TickGet() - startTickCount >= timeoutPeriod) { #if defined(__Digilent_Build__) break; #else WF_ASSERT(FALSE); #endif } } while (value == 0); }
/***************************************************************************** * FUNCTION: RawMove * * RETURNS: Number of bytes that were overlayed (not always applicable) * * PARAMS: * rawId - RAW ID * srcDest - MRF24W object that will either source or destination of move * rawIsDestination - TRUE if RAW engine is the destination, FALSE if its the source * size - number of bytes to overlay (not always applicable) * * NOTES: Performs a RAW move operation between a RAW engine and a MRF24W object *****************************************************************************/ static UINT16 RawMove(UINT16 rawId, UINT16 srcDest, BOOL rawIsDestination, UINT16 size) { UINT16 byteCount; UINT8 regId; UINT8 regValue8; UINT16 ctrlVal = 0; 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) */ /* Clear the interrupt bit in the register */ regValue8 = (rawId == RAW_ID_0)? WF_HOST_INT_MASK_RAW_0_INT_0 : WF_HOST_INT_MASK_RAW_1_INT_0; Write8BitWFRegister(WF_HOST_INTR_REG, regValue8); /* write update control value to register to control register */ regId = (rawId == RAW_ID_0) ? RAW_0_CTRL_0_REG : RAW_1_CTRL_0_REG; Write16BitWFRegister(regId, ctrlVal); // Wait for the RAW move operation to complete, and read back the number of bytes, if any, that were overlayed byteCount = WaitForRawMoveComplete(rawId); return byteCount; }
/***************************************************************************** * FUNCTION: RawSetIndex * * RETURNS: True is success, false if timed out, which means attempted to set * raw index past end of raw window. Not a problem as long as no read * or write occurs. * * PARAMS: * rawId - RAW ID * index - desired index * * NOTES: Sets the RAW index for the specified RAW engine. If attempt to set RAW * index outside boundaries of RAW window this function will time out. *****************************************************************************/ BOOL RawSetIndex(UINT16 rawId, UINT16 index) { UINT8 regId; UINT16 regValue; UINT32 startTickCount; UINT32 maxAllowedTicks; // set the RAW index regId = (rawId==RAW_ID_0)?RAW_0_INDEX_REG:RAW_1_INDEX_REG; Write16BitWFRegister(regId, index); startTickCount = (UINT32)TickGet(); maxAllowedTicks = TICKS_PER_SECOND / 200; /* 5ms */ regId = (rawId==RAW_ID_0)?RAW_0_STATUS_REG:RAW_1_STATUS_REG; while (1) { regValue = Read16BitWFRegister(regId); if ((regValue & WF_RAW_STATUS_REG_BUSY_MASK) == 0) { return TRUE; } /* if timed out then trying to set index past end of raw window, which is OK so long as the app */ /* doesn't try to access it */ if (TickGet() - startTickCount >= maxAllowedTicks) { return FALSE; /* timed out waiting for Raw set index to complete */ } } }
/***************************************************************************** * FUNCTION: RawSetIndex * * RETURNS: True is success, false if timed out, which means attempted to set * raw index past end of raw window. Not a problem as long as no read * or write occurs. * * PARAMS: * rawId - RAW ID * index - desired index * * NOTES: Sets the RAW index for the specified RAW engine. If attempt to set RAW * index outside boundaries of RAW window this function will time out. *****************************************************************************/ bool RawSetIndex(uint16_t rawId, uint16_t index) { uint8_t regId; uint16_t regValue; uint32_t startTickCount; uint32_t maxAllowedTicks; // set the RAW index regId = (rawId==RAW_ID_0) ? RAW_0_INDEX_REG:RAW_1_INDEX_REG; Write16BitWFRegister(regId, index); startTickCount = (uint32_t)TickGet(); maxAllowedTicks = TICKS_PER_SECOND / 200; /* 5ms */ regId = (rawId==RAW_ID_0) ? RAW_0_STATUS_REG:RAW_1_STATUS_REG; while (1) { regValue = Read16BitWFRegister(regId); if ((regValue & WF_RAW_STATUS_REG_BUSY_MASK) == 0) { return true; } /* if timed out then trying to set index past end of raw window, which is OK so long as the app */ /* doesn't try to access it */ if (TickGet() - startTickCount >= maxAllowedTicks) { return false; /* timed out waiting for Raw set index to complete */ } } }
/******************************************************************************* Function: void WFConfigureLowPowerMode(UINT8 action) Summary: Driver function to configure PS Poll mode. Description: This function is only used by the driver, not the application. This function, other than at initialization, is only used when the application has enabled PS-Poll mode. This function is used to temporarily deactivate PS-Poll mode when there is mgmt or data message tx/rx and then, when message activity has ceased, to again activate PS-Poll mode. Precondition: MACInit must be called first. Parameters: action - Can be either: * WF_LOW_POWER_MODE_ON * WF_LOW_POWER_MODE_OFF Returns: None. Remarks: None. *****************************************************************************/ void WFConfigureLowPowerMode(UINT8 action) { UINT16 lowPowerStatusRegValue; /*-----------------------------------------*/ /* if activating PS-Poll mode on MRF24W */ /*-----------------------------------------*/ if (action == WF_LOW_POWER_MODE_ON) { //putrsUART("Enable PS\r\n"); Write16BitWFRegister(WF_PSPOLL_H_REG, REG_ENABLE_LOW_POWER_MASK); g_psPollActive = TRUE; } /*---------------------------------------------------------------------------------------------*/ /* else deactivating PS-Poll mode on MRF24W (taking it out of low-power mode and waking it up) */ /*---------------------------------------------------------------------------------------------*/ else /* action == WF_LOW_POWER_MODE_OFF */ { //putrsUART("Disable PS\r\n"); Write16BitWFRegister(WF_PSPOLL_H_REG, REG_DISABLE_LOW_POWER_MASK); g_psPollActive = FALSE; /* poll the response bit that indicates when the MRF24W has come out of low power mode */ do { #if defined(MRF24WG) /* set the index register to the register we wish to read */ Write16BitWFRegister(WF_INDEX_ADDR_REG, WF_SCRATCHPAD_1_REG); #else /* must be a MRF24WB */ /* set the index register to the register we wish to read */ Write16BitWFRegister(WF_INDEX_ADDR_REG, WF_LOW_POWER_STATUS_REG); #endif lowPowerStatusRegValue = Read16BitWFRegister(WF_INDEX_DATA_REG); } while (lowPowerStatusRegValue & REG_ENABLE_LOW_POWER_MASK); } }
/***************************************************************************** Function: void 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: None Remarks: None *****************************************************************************/ static void RawMove(uint16_t rawId, uint16_t srcDest, bool rawIsDestination, uint16_t size) { uint8_t regId; uint16_t ctrlVal = 0; g_rawMoveWaitState.rawId = rawId; /* create control value that will be written to raw control register, which initiates the raw move */ if (rawIsDestination) { ctrlVal |= 0x8000; } 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) */ // needs to be set before doing raw move RawMoveState[rawId].rawInterrupt = 0; RawMoveState[rawId].waitingForRawMoveCompleteInterrupt = true; /*------------------------------------------------------------------------------------------------*/ /* 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 */ /* 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 */ g_rawMoveWaitState.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 */ g_rawMoveWaitState.rawIntMask = WF_HOST_INT_MASK_INT2; } StartRawMoveTimer(rawId); }
/***************************************************************************** Function: BOOL RawSetIndex(UINT16 rawId, UINT16 index) Summary: Sets the index within the specified RAW window. Description: Sets the index within the specified RAW window. If attempt to set RAW index outside boundaries of RAW window (past the end) this function will time out. It's legal to set the index past the end of the raw window so long as there is no attempt to read or write at that index. Precondition: None Parameters: rawId -- RAW window ID index -- desired index within RAW window Returns: True if successful, False if caller tried to set raw index past end of window Remarks: None *****************************************************************************/ BOOL RawSetIndex(UINT16 rawId, UINT16 index) { UINT8 regId; UINT16 regValue; UINT32 startTickCount; UINT32 maxAllowedTicks; /* get the index register associated with the raw ID and write to it */ regId = g_RawIndexReg[rawId]; Write16BitWFRegister(regId, index); /* Get the raw status register address associated with the raw ID. This will be polled to */ /* determine that: */ /* 1) raw set index completed successfully OR */ /* 2) raw set index failed, implying that the raw index was set past the end of the raw window */ regId = g_RawStatusReg[rawId]; maxAllowedTicks = TICKS_PER_SECOND / 200; /* 5ms */ startTickCount = (UINT32)TickGet(); /* read the status register until set index operation completes or times out */ while (1) { regValue = Read16BitWFRegister(regId); if ((regValue & WF_RAW_STATUS_REG_BUSY_MASK) == 0) { ClearIndexOutOfBoundsFlag(rawId); return TRUE; } /* if timed out then trying to set index past end of raw window, which is OK so long as the app */ /* doesn't try to access it */ if (TickGet() - startTickCount >= maxAllowedTicks) { SetIndexOutOfBoundsFlag(rawId); return FALSE; /* timed out waiting for Raw set index to complete */ } } }
/***************************************************************************** Function: void RawSetIndex(uint16_t rawId, uint16_t index) Summary: Sets the index within the specified RAW window. Description: Sets the index within the specified RAW window. If attempt to set RAW index outside boundaries of RAW window (past the end) this function will time out. It's legal to set the index past the end of the raw window so long as there is no attempt to read or write at that index. For now, flag an event. Precondition: None Parameters: rawId -- RAW window ID index -- desired index within RAW window Returns: None Remarks: None *****************************************************************************/ void RawSetIndex(uint16_t rawId, uint16_t index) { uint8_t regId; uint16_t regValue; uint32_t elapsedTime; uint32_t startTime; /* get the index register associated with the raw ID and write to it */ regId = g_RawIndexReg[rawId]; Write16BitWFRegister(regId, index); /* Get the raw status register address associated with the raw ID. This will be polled to */ /* determine that: */ /* 1) raw set index completed successfully OR */ /* 2) raw set index failed, implying that the raw index was set past the end of the raw window */ regId = g_RawStatusReg[rawId]; /* read the status register until set index operation completes or times out */ startTime = WF_TimerRead(); while (1) { regValue = Read16BitWFRegister(regId); if ((regValue & WF_RAW_STATUS_REG_BUSY_MASK) == 0) { ClearIndexOutOfBoundsFlag(rawId); break; } elapsedTime = GetElapsedTime(startTime, WF_TimerRead()); if (elapsedTime > 5) { // if we timed out that means that the caller is trying to set the index // past the end of the raw window. Not illegal in of itself so long // as there is no attempt to read or write at this location. But, // applications should avoid this to avoid the timeout in SetIndexOutOfBoundsFlag(rawId); EventEnqueue(WF_EVENT_ERROR, UD_ERROR_RAW_SET_INDEX_OUT_OF_BOUNDS); break; } } }
/***************************************************************************** Function: bool RawSetIndex(uint16_t rawId, uint16_t index) Summary: Sets the index within the specified RAW window. Description: Sets the index within the specified RAW window. If attempt to set RAW index outside boundaries of RAW window (past the end) this function will time out. It's legal to set the index past the end of the raw window so long as there is no attempt to read or write at that index. Precondition: None Parameters: rawId -- RAW window ID index -- desired index within RAW window Returns: True if successful, False if caller tried to set raw index past end of window Remarks: None *****************************************************************************/ bool RawSetIndex(uint16_t rawId, uint16_t index) { uint8_t regId; uint16_t regValue; uint32_t startTickCount; uint32_t maxAllowedTicks; /* get the index register associated with the raw ID and write to it */ regId = g_RawIndexReg[rawId]; Write16BitWFRegister(regId, index); /* Get the raw status register address associated with the raw ID. This will be polled to */ /* determine that: */ /* 1) raw set index completed successfully OR */ /* 2) raw set index failed, implying that the raw index was set past the end of the raw window */ regId = g_RawStatusReg[rawId]; maxAllowedTicks = SYS_TMR_TickPerSecond() / 200; /* 5ms */ startTickCount = SYS_TMR_TickCountGet(); /* read the status register until set index operation completes or times out */ while (1) { regValue = Read16BitWFRegister(regId); if ((regValue & WF_RAW_STATUS_REG_BUSY_MASK) == 0) { ClearIndexOutOfBoundsFlag(rawId); return true; } /* if timed out then trying to set index past end of raw window, which is OK so long as the app */ /* doesn't try to access it */ if (SYS_TMR_TickCountGet() - startTickCount >= maxAllowedTicks) { SetIndexOutOfBoundsFlag(rawId); return false; /* timed out waiting for Raw set index to complete */ } } }
/***************************************************************************** * FUNCTION: RawMove * * RETURNS: Number of bytes that were overlayed (not always applicable) * * PARAMS: * rawId - RAW ID * srcDest - MRF24W object that will either source or destination of move * rawIsDestination - true if RAW engine is the destination, false if its the source * size - number of bytes to overlay (not always applicable) * * NOTES: Performs a RAW move operation between a RAW engine and a MRF24W object *****************************************************************************/ static uint16_t RawMove(uint16_t rawId, uint16_t srcDest, bool rawIsDestination, uint16_t size) { uint16_t byteCount; uint8_t regId; uint8_t regValue8; uint16_t ctrlVal = 0; if (rawIsDestination) { ctrlVal |= 0x8000; } /* fix later, simply need to ensure that size is 12 bits are less */ /* if size is legal, (bits 11:0) of ctrlVal contains the information of size, */ /* (bits 15:12) of ctriVal contains the information of srcDest */ 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) */ /* Clear the interrupt bit in the register */ regValue8 = (rawId == RAW_ID_0) ? WF_HOST_INT_MASK_RAW_0_INT_0:WF_HOST_INT_MASK_RAW_1_INT_0; Write8BitWFRegister(WF_HOST_INTR_REG, regValue8); /* write update control value to register to control register */ regId = (rawId==RAW_ID_0) ? RAW_0_CTRL_0_REG:RAW_1_CTRL_0_REG; gIntDisabled = WF_EintIsDisabled(); WF_EintDisable(); Write16BitWFRegister(regId, ctrlVal); // Wait for the RAW move operation to complete, and read back the number of bytes, if any, that were overlayed byteCount = WaitForRawMoveComplete(rawId); return byteCount; }
/***************************************************************************** * FUNCTION: RawSetIndex * * RETURNS: True is success, false if timed out, which means attempted to set * raw index past end of raw window. Not a problem as long as no read * or write occurs. * * PARAMS: * rawId - RAW ID * index - desired index * * NOTES: Sets the RAW index for the specified RAW engine. If attempt to set RAW * index outside boundaries of RAW window this function will time out. *****************************************************************************/ bool RawSetIndex(uint16_t rawId, uint16_t index) { uint8_t regId; uint16_t regValue; SYS_TICK startTickCount; SYS_TICK maxAllowedTicks; // set the RAW index regId = (rawId==RAW_ID_0)?RAW_0_INDEX_REG:RAW_1_INDEX_REG; Write16BitWFRegister(regId, index); startTickCount = SYS_TICK_Get(); maxAllowedTicks = SYS_TICK_TicksPerSecondGet() / 200; /* 5ms */ if(maxAllowedTicks == 0) { maxAllowedTicks++; // at least one system tick } regId = (rawId==RAW_ID_0)?RAW_0_STATUS_REG:RAW_1_STATUS_REG; while (1) { regValue = Read16BitWFRegister(regId); if ((regValue & WF_RAW_STATUS_REG_BUSY_MASK) == 0) { return true; } /* if timed out then trying to set index past end of raw window, which is OK so long as the app */ /* doesn't try to access it */ if (SYS_TICK_Get() - startTickCount >= maxAllowedTicks) { return false; /* timed out waiting for Raw set index to complete */ } } }
/* * 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: uint16_t WF_ReadMgmtBase(void) Summary: Retrieves WF Mgmt base address Description: Precondition: MACInit must be called first. Parameters: None Returns: Base address Remarks: None. *****************************************************************************/ uint16_t WF_ReadMgmtBase(void) { Write16BitWFRegister(WF_INDEX_ADDR_REG, WF_SCRATCHPAD_0_REG); return Read16BitWFRegister(WF_INDEX_DATA_REG); }
/***************************************************************************** * 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: 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/RAW1 Move Complete interrupt occurred or a level 2 interrupt occurred, indicating */ /* that a RAW2-5 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)) { /* save the copy of the active interrupts */ RawMoveState.rawInterrupt = g_EintHostInt; RawMoveState.waitingForRawMoveCompleteInterrupt = FALSE; /* 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 Completet 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); } } /*--------------------------------------------------------------------------------------------------*/ /* 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(); } } // 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; }
static void WriteAnalogRegisterBitBang(UINT8 regType, UINT16 address, UINT16 value) { UINT8 spiPort; UINT16 hrVal; UINT8 bitMask8; UINT16 bitMask16; UINT8 i; UINT8 regAddress; spiPort = GetSpiPortWithBitBang(regType); // extract SPI port (0-3) from the register type // Enable the on-chip SPI and select the desired bank (0-3) hrVal = (HR_HOST_ANA_SPI_EN_MASK | (spiPort << 6)); Write16BitWFRegister(WF_HOST_RESET_REG, hrVal); // create register address byte regAddress = (address << 2) | SPI_AUTO_INCREMENT_ENABLED_MASK | SPI_WRITE_MASK; // bit-bang the regAddress byte, MS bit to LS bit bitMask8 = 0x80; // start with MS bit of byte being bit-banged out for (i = 0; i < 8; ++i) { hrVal &= ~(HR_HOST_ANA_SPI_DOUT_MASK | HR_HOST_ANA_SPI_CLK_MASK); // zero out DOUT and CLK // mask out ADDRESS bit being clocked and write to HOST_ANA_SPI_DOUT (bit 10) in HOST_RESET_REG with the HOST_ANA_SPI_CLK low if ((regAddress & bitMask8) > 0) { hrVal |= HR_HOST_ANA_SPI_DOUT_MASK; } Write16BitWFRegister(WF_HOST_RESET_REG, hrVal); // now toggle SPI clock high, on rising edge this bit is clocked out hrVal |= HR_HOST_ANA_SPI_CLK_MASK; Write16BitWFRegister(WF_HOST_RESET_REG, hrVal); bitMask8 >>= 1; // # get to next bit in address byte } // bit bang data from MS bit to LS bit bitMask16 = 0x8000; // start with MS bit of byte being bit-banged out for (i = 0; i < 16; ++i) { hrVal &= ~(HR_HOST_ANA_SPI_DOUT_MASK | HR_HOST_ANA_SPI_CLK_MASK); // zero out DOUT and CLK // mask in data bit being clock out and write to HOST_ANA_SPI_DOUT (bit 10) in HOST_RESET_REG with the HOST_ANA_SPI_CLK low if ((value & bitMask16) > 0) { hrVal |= HR_HOST_ANA_SPI_DOUT_MASK; } Write16BitWFRegister(WF_HOST_RESET_REG, hrVal); // now toggle SPI clock high, on rising edge this bit is clocked out hrVal |= HR_HOST_ANA_SPI_CLK_MASK; Write16BitWFRegister(WF_HOST_RESET_REG, hrVal); bitMask16 = bitMask16 >> 1; // go to next bit in data byte } // Disable the on-chip SPI hrVal &= ~HR_HOST_ANA_SPI_EN_MASK; Write16BitWFRegister(WF_HOST_RESET_REG, hrVal); }
/***************************************************************************** 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(); } }