/******************************************************************************* Function: void WaitForMgmtResponseAndReadData(UINT8 expectedSubtype, UINT8 numDataBytes, UINT8 startIndex, UINT8 *p_data) Summary: Waits for a management response and read data. Description: Waits for the mgmt response message and validates it by: 1) checking the result field 2) verifying that the received subtype matches the expected subtype In addition, this function reads the desired number of data bytes from the mgmt response, copies them to p_data, and then frees the mgmt buffer. Precondition: MACInit must be called. Parameters: expectedSubtype -- management message subtype that we are expecting p_data -- pointer where any desired management data bytes will be written numDataBytes -- Number of data bytes from mgmt response to write to p_data. Data always starts at index 4 of mgmt response. skipDataRead -- if TRUE, then no data will be read and the mgmt buffer will not be freed. If FALSE, the data will be read and the mgmt buffer will be freed. Returns: None Remarks: *****************************************************************************/ void WaitForMgmtResponseAndReadData(UINT8 expectedSubtype, UINT8 numDataBytes, UINT8 startIndex, UINT8 *p_data) { tMgmtMsgRxHdr hdr; /* management msg header struct */ WaitForMgmtResponse(expectedSubtype, DO_NOT_FREE_MGMT_BUFFER); /* if made it here then received a management message */ RawRead(RAW_MGMT_RX_ID, 0, (UINT16)(sizeof(tMgmtMsgRxHdr)), (UINT8 *)&hdr); /* check header result and subtype fields */ WF_ASSERT(hdr.result == WF_SUCCESS || hdr.result == WF_ERROR_NO_STORED_BSS_DESCRIPTOR); WF_ASSERT(hdr.subtype == expectedSubtype); /* if caller wants to read data from this mgmt response */ if (numDataBytes > 0) { RawRead(RAW_MGMT_RX_ID, startIndex, numDataBytes, p_data); } /* free the mgmt buffer */ DeallocateMgmtRxBuffer(); }
/***************************************************************************** Function: BOOL AllocateDataTxBuffer(UINT16 bytesNeeded) Summary: Allocates a Data Tx buffer for use by the TCP/IP stack. Description: Determines if WiFi chip has enough memory to allocate a tx data buffer, and, if so, allocates it. Precondition: None Parameters: bytesNeeded -- number of bytes needed for the data tx message Returns: True if data tx buffer successfully allocated, else False Remarks: None *****************************************************************************/ BOOL AllocateDataTxBuffer(UINT16 bytesNeeded) { UINT16 bufAvail; UINT16 byteCount; WF_ASSERT(GetRawWindowState(RAW_DATA_TX_ID) != WF_RAW_DATA_MOUNTED); /* Ensure the MRF24W is awake (only applies if PS-Poll was enabled) */ EnsureWFisAwake(); /* get total bytes available for DATA tx memory pool */ bufAvail = Read16BitWFRegister(WF_HOST_WFIFO_BCNT0_REG) & 0x0fff; /* LS 12 bits contain length */ /* if enough bytes available to allocate */ if ( bufAvail >= bytesNeeded ) { /* allocate and create the new Tx buffer (mgmt or data) */ byteCount = RawMove(RAW_DATA_TX_ID, RAW_DATA_POOL, TRUE, bytesNeeded); WF_ASSERT(byteCount != 0); /* flag this raw window as mounted (in use) */ SetRawWindowState(RAW_DATA_TX_ID, WF_RAW_DATA_MOUNTED); return TRUE; } /* else not enough bytes available at this time to satisfy request */ else { return FALSE; } }
/***************************************************************************** * FUNCTION: WaitForMgmtRespAndReadData * * RETURNS: None * * PARAMS: expectedSubtype -- management message subtype that we are expecting * p_data -- pointer where any desired management data bytes * will be written * numDataBytes -- Number of data bytes from mgmt response to write to * p_data. Data always starts at index 4 of mgmt response. * skipDataRead -- if TRUE, then no data will be read and the mgmt buffer will not * be freed. If FALSE, the data will be read and the mgmt buffer * will be freed. * * NOTES: Waits for the mgmt response message and validates it by: * 1) checking the result field * 2) verifying that the received subtype matches the execpted subtype * * In addition, this function reads the desired number of data bytes from * the mgmt response, copies them to p_data, and then frees the mgmt buffer. *****************************************************************************/ void WaitForMgmtResponseAndReadData(UINT8 expectedSubtype, UINT8 numDataBytes, UINT8 startIndex, UINT8 *p_data) { tMgmtMsgRxHdr hdr; /* management msg header struct */ WaitForMgmtResponse(expectedSubtype, DO_NOT_FREE_MGMT_BUFFER); /* if made it here then received a management message */ RawRead(RAW_RX_ID, 0, (UINT16)(sizeof(tMgmtMsgRxHdr)), (UINT8 *)&hdr); /* check header result and subtype fields */ WF_ASSERT(hdr.result == WF_SUCCESS || hdr.result == WF_ERROR_NO_STORED_BSS_DESCRIPTOR); WF_ASSERT(hdr.subtype == expectedSubtype); /* if caller wants to read data from this mgmt response */ if (numDataBytes > 0) { RawRead(RAW_RX_ID, startIndex, numDataBytes, p_data); } /* free the 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); } }
/* ********************************************************************************************************* * 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: 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: 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: 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: void WF_MulticastGetConfig(uint8_t filterId, tWFMultiCastConfig *p_config); Summary: Gets a multicast address filter from one of the two multicast filters. Description: Gets the current state of the specified Multicast Filter. Normally would call SendGetParamMsg, but this GetParam returns all 6 address filters + 2 more bytes for a total of 48 bytes plus header. So, doing this msg manually to not require a large stack allocation to hold all the data. Exact format of management message stored on device is: [0] -- always mgmt response (2) [1] -- always WF_GET_PARAM_SUBTYPE (16) [2] -- result (1 if successful) [3] -- mac state (not used) [4] -- data length (length of response data starting at index 6) [5] -- not used [6-11] -- Compare Address 0 address [12] -- Compare Address 0 group [13] -- Compare Address 0 type [14] -- Compare Address 0 macBitMask [15-17] -- Not used [18-23] -- Compare Address 1 address [24] -- Compare Address 1 group [25] -- Compare Address 1 type [26] -- Compare Address 1 macBitMask [27-29] -- Not used [30-35] -- Compare Address 2 address [36] -- Compare Address 2 group [37] -- Compare Address 2 type [38] -- Compare Address 2 macBitMask [39-41] -- Not used [42-47] -- Compare Address 3 address [48] -- Compare Address 3 group [49] -- Compare Address 3 type [50] -- Compare Address 3 macBitMask [51-53] -- Not used [54-59] -- Compare Address 4 address [60] -- Compare Address 4 group [61] -- Compare Address 4 type [62] -- Compare Address 4 macBitMask [63-65] -- Not used [66-71] -- Compare Address 5 address [72] -- Compare Address 5 group [73] -- Compare Address 5 type [74] -- Compare Address 5 macBitMask [75-77] -- Not used Precondition: MACInit must be called first. Parameters: filterId -- ID of filter being retrieved. Must be: WF_MULTICAST_FILTER_1 or WF_MULTICAST_FILTER_2 p_config -- Pointer to config structure filled in by this function. Returns: None. Remarks: Definition WF_USE_MULTICAST_FUNCTIONS needs to be enabled. *****************************************************************************/ void WF_MulticastGetConfig(uint8_t filterId, tWFMultiCastConfig *p_config) { uint8_t hdr[4]; uint8_t paramData[12]; WF_ASSERT( filterId <= WF_MULTICAST_FILTER_16); hdr[0] = WF_MGMT_REQUEST_TYPE; hdr[1] = WF_GET_PARAM_SUBTYPE; hdr[2] = 0x00; /* MS 8 bits of param Id, always 0 */ hdr[3] = PARAM_COMPARE_ADDRESS; /* LS 8 bits of param ID */ SendMgmtMsg(hdr, /* header */ sizeof(hdr), /* size of header */ &filterId, /* multicast filter id */ 1); /* length is 1 */ WaitForMgmtResponseAndReadData(WF_GET_PARAM_SUBTYPE, /* expected subtype */ sizeof(paramData), /* num data bytes to read */ MSG_PARAM_START_DATA_INDEX, /* starting at this index */ paramData); /* write the response data here */ /* put param data into return structure */ p_config->filterId = filterId; memcpy((void *)p_config->macBytes, (void *)¶mData[0], 6); p_config->action = paramData[7]; p_config->macBitMask = paramData[8]; }
/***************************************************************************** * 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: RawGetByte * * RETURNS: error code * * PARAMS: * rawId - RAW ID * pBuffer - Buffer to read bytes into * length - number of bytes to read * * NOTES: Reads bytes from the RAW engine *****************************************************************************/ void RawGetByte(uint16_t rawId, uint8_t *pBuffer, uint16_t length) { uint8_t regId; #if defined(OUTPUT_RAW_TX_RX) uint16_t i; #endif /* if reading a data message do following check */ if (!g_WaitingForMgmtResponse) { // if RAW index previously set out of range and caller is trying to do illegal read if ( (rawId==RAW_RX_ID) && g_rxIndexSetBeyondBuffer && (GetRawWindowState(RAW_RX_ID) == WF_RAW_DATA_MOUNTED) ) { WF_ASSERT(false); /* attempting to read past end of RAW buffer */ } } regId = (rawId==RAW_ID_0) ? RAW_0_DATA_REG:RAW_1_DATA_REG; ReadWFArray(regId, pBuffer, length); #if defined(OUTPUT_RAW_TX_RX) for (i = 0; i < length; ++i) { char buf[16]; sprintf(buf,"R: %#x\r\n", pBuffer[i]); putsUART(buf); } #endif }
/***************************************************************************** * FUNCTION: RawSetByte * * RETURNS: None * * PARAMS: * rawId - RAW ID * pBuffer - Buffer containing bytes to write * length - number of bytes to read * * NOTES: Writes bytes to RAW window *****************************************************************************/ void RawSetByte(UINT16 rawId, UINT8 *pBuffer, UINT16 length) { UINT8 regId; #if defined(OUTPUT_RAW_TX_RX) UINT16 i; #endif /* if previously set index past legal range and now trying to write to RAW engine */ if ( (rawId == 0) && g_rxIndexSetBeyondBuffer && (GetRawWindowState(RAW_TX_ID) == WF_RAW_DATA_MOUNTED) ) { WF_ASSERT(FALSE); /* attempting to write past end of RAW window */ } /* write RAW data to chip */ regId = (rawId==RAW_ID_0)?RAW_0_DATA_REG:RAW_1_DATA_REG; WriteWFArray(regId, pBuffer, length); #if defined(OUTPUT_RAW_TX_RX) for (i = 0; i < length; ++i) { char buf[16]; sprintf(buf,"T: %#x\r\n", pBuffer[i]); putsUART(buf); } #endif }
/******************************************************************************* Function: void WF_SetMultiCastFilter(UINT8 multicastFilterId, UINT8 multicastAddress[6]) Summary: Sets a multicast address filter using one of the two multicast filters. Description: This function allows the application to configure up to two Multicast Address Filters on the MRF24WB0M. If two active multicast filters are set up they are OR’d together – the MRF24WB0M will receive and pass to the Host CPU received packets from either multicast address. The allowable values for the multicast filter are: * WF_MULTICAST_FILTER_1 * WF_MULTICAST_FILTER_2 By default, both Multicast Filters are inactive. Precondition: MACInit must be called first. Parameters: multicastFilterId - WF_MULTICAST_FILTER_1 or WF_MULTICAST_FILTER_2 multicastAddress - 6-byte address (all 0xFF will inactivate the filter) Returns: None. Remarks: None. *****************************************************************************/ void WF_SetMultiCastFilter(UINT8 multicastFilterId, UINT8 multicastAddress[6]) { int i; BOOL deactivateFlag = TRUE; UINT8 msgData[8]; WF_ASSERT( (multicastFilterId == WF_MULTICAST_FILTER_1) || (multicastFilterId == WF_MULTICAST_FILTER_2) ); /* check if all 6 bytes of the address are 0xff, implying that the caller wants to deactivate */ /* the multicast filter. */ for (i = 0; i < 6; ++i) { /* if any byte is not 0xff then a presume a valid multicast address */ if (multicastAddress[i] != 0xff) { deactivateFlag = FALSE; break; } } msgData[0] = multicastFilterId; /* Address Compare Register number to use */ if (deactivateFlag) { msgData[1] = ADDRESS_FILTER_DEACTIVATE; } else { msgData[1] = MULTICAST_ADDRESS; /* type of address being used in the filter */ } memcpy(&msgData[2], (void *)multicastAddress, WF_MAC_ADDRESS_LENGTH); SendSetParamMsg(PARAM_COMPARE_ADDRESS, msgData, sizeof(msgData) ); }
/***************************************************************************** Function: BOOL AllocateMgmtTxBuffer(UINT16 bytesNeeded) Summary: Allocates a Mgmt Tx buffer Description: Determines if WiFi chip has enough memory to allocate a tx mgmt buffer, and, if so, allocates it. Precondition: None Parameters: bytesNeeded -- number of bytes needed for the mgmt tx message Returns: True if mgmt tx buffer successfully allocated, else False Remarks: None *****************************************************************************/ BOOL AllocateMgmtTxBuffer(UINT16 bytesNeeded) { UINT16 bufAvail; UINT16 byteCount; /* get total bytes available for MGMT tx memory pool */ bufAvail = Read16BitWFRegister(WF_HOST_WFIFO_BCNT1_REG) & 0x0fff; /* LS 12 bits contain length */ /* if enough bytes available to allocate */ if ( bufAvail >= bytesNeeded ) { /* allocate and create the new Mgmt Tx buffer */ byteCount = RawMove(RAW_MGMT_TX_ID, RAW_MGMT_POOL, TRUE, bytesNeeded); WF_ASSERT(byteCount != 0); return TRUE; } /* else not enough bytes available at this time to satisfy request */ else { /* if we allocated some bytes, but not enough, then dealloacate what was allocated */ if (bufAvail > 0) { RawMove(RAW_MGMT_RX_ID, RAW_MGMT_POOL, FALSE, 0); } return FALSE; } }
/***************************************************************************** * FUNCTION: RawGetByte * * RETURNS: error code * * PARAMS: * rawId - RAW ID * pBuffer - Buffer to read bytes into * length - number of bytes to read * * NOTES: Reads bytes from the RAW engine *****************************************************************************/ void RawGetByte(UINT16 rawId, UINT8 *pBuffer, UINT16 length) { UINT8 regId; #if defined(OUTPUT_RAW_TX_RX) char buf[8]; #endif /* if reading a data message do following check */ if (!g_WaitingForMgmtResponse) { // if RAW index previously set out of range and caller is trying to do illegal read if ((rawId == RAW_RX_ID) && g_rxIndexSetBeyondBuffer && (GetRawWindowState(RAW_RX_ID) == WF_RAW_DATA_MOUNTED)) { WF_ASSERT(FALSE); /* attempting to read past end of RAW buffer */ } } regId = (rawId == RAW_ID_0) ? RAW_0_DATA_REG : RAW_1_DATA_REG; ReadWFArray(regId, pBuffer, length); #if defined(OUTPUT_RAW_TX_RX) putrsUART("R:"); while (length-- != 0) { sprintf(buf," %02X", *pBuffer++); putsUART(buf); } putrsUART("\r\n"); #endif }
BOOL AllocateMgmtTxBuffer(UINT16 bytesNeeded) { UINT16 bufAvail; UINT16 byteCount; /* get total bytes available for MGMT tx memory pool */ bufAvail = Read16BitWFRegister(WF_HOST_WFIFO_BCNT1_REG) & 0x0fff; /* LS 12 bits contain length */ /* if enough bytes available to allocate */ if ( bufAvail >= bytesNeeded ) { /* allocate and create the new Tx buffer (mgmt or data) */ byteCount = RawMove(RAW_TX_ID, RAW_MGMT_POOL, TRUE, bytesNeeded); WF_ASSERT(byteCount != 0); } /* else not enough bytes available at this time to satisfy request */ else { return FALSE; } RawWindowReady[RAW_TX_ID] = TRUE; SetRawWindowState(RAW_TX_ID, WF_RAW_MGMT_MOUNTED); return TRUE; }
/***************************************************************************** Function: void WFSpiTxRx(void) Summary: Transmits and receives SPI bytes Description: Transmits and receives N bytes of SPI data. Precondition: None Parameters: p_txBuf - pointer to SPI tx data txLen - number of bytes to Tx p_rxBuf - pointer to where SPI rx data will be stored rxLen - number of SPI rx bytes caller wants copied to p_rxBuf Returns: None Remarks: Will clock out the larger of txLen or rxLen, and pad if necessary. *****************************************************************************/ void WFSpiTxRx(UINT8 *p_txBuf, UINT16 txLen, UINT8 *p_rxBuf, UINT16 rxLen) { #if defined(__18CXX) static UINT16 byteCount; /* avoid local variables in functions called from interrupt routine */ static UINT16 i; static UINT8 rxTrash; #else UINT16 byteCount; UINT16 i; UINT8 rxTrash; #endif #ifdef WF_DEBUG /* Cannot communicate with MRF24WB0M when it is in hibernate mode */ { static UINT8 state; /* avoid local vars in functions called from interrupt */ WF_GetPowerSaveState(&state); WF_ASSERT(state != WF_PS_HIBERNATE); } #endif /* total number of byte to clock is whichever is larger, txLen or rxLen */ byteCount = (txLen >= rxLen)?txLen:rxLen; for (i = 0; i < byteCount; ++i) { /* if still have bytes to transmit from tx buffer */ if (txLen > 0) { WF_SSPBUF = *p_txBuf++; --txLen; } /* else done writing bytes out from tx buffer */ else { WF_SSPBUF = 0xff; /* clock out a "don't care" byte */ } /* wait until tx/rx byte to completely clock out */ WaitForDataByte(); /* if still have bytes to read into rx buffer */ if (rxLen > 0) { *p_rxBuf++ = WF_SSPBUF; --rxLen; } /* else done reading bytes into rx buffer */ else { rxTrash = WF_SSPBUF; /* read and throw away byte */ } } /* end for loop */ }
/******************************************************************************* Function: void WF_SetRtsThreshold(UINT16 rtsThreshold) Summary: Sets the RTS Threshold. Description: Sets the RTS/CTS packet size threshold for when RTS/CTS frame will be sent. The default is 2347 bytes – the maximum for 802.11. It is recommended that the user leave the default at 2347 until they understand the performance and power ramifications of setting it smaller. Valid values are from 0 to WF_RTS_THRESHOLD_MAX (2347). Precondition: MACInit must be called first. Parameters: rtsThreshold - Value of the packet size threshold Returns: None. Remarks: None. *****************************************************************************/ void WF_SetRtsThreshold(UINT16 rtsThreshold) { WF_ASSERT(rtsThreshold <= WF_RTS_THRESHOLD_MAX); /* correct endianness before sending message */ rtsThreshold = HSTOWFS(rtsThreshold); SendSetParamMsg(PARAM_RTS_THRESHOLD, (UINT8 *)&rtsThreshold, sizeof(rtsThreshold)); }
/***************************************************************************** * FUNCTION: RawGetByte * * RETURNS: error code * * PARAMS: * rawId - RAW ID * pBuffer - Buffer to read bytes into * length - number of bytes to read * * NOTES: Reads bytes from the RAW engine *****************************************************************************/ void RawGetByte(UINT16 rawId, UINT8 *pBuffer, UINT16 length) { UINT8 regId; WF_ASSERT(!isIndexOutOfBounds(rawId)); /* attempting to read past end of RAW buffer */ regId = g_RawDataReg[rawId]; ReadWFArray(regId, pBuffer, length); }
/***************************************************************************** Function: UINT16 ScratchMount(UINT8 rawId) Summary: Mounts RAW scratch window Description: The scratch window is not dynamically allocated, but references a static portion of the WiFi device RAM. Thus, the Scratch data is not lost when the scratch window is unmounted. Precondition: None Parameters: rawId -- RAW window ID being used to mount the scratch data Returns: Size, in bytes, of Scratch buffer Remarks: None *****************************************************************************/ UINT16 ScratchMount(UINT8 rawId) { UINT16 byteCount; byteCount = RawMove(rawId, RAW_SCRATCH_POOL, TRUE, 0); WF_ASSERT(byteCount > 0); /* scratch mount should always return value > 0 */ return byteCount; }
/******************************************************************************* Function: void WF_CPSetSsid(UINT8 CpId, UINT8 *p_ssid, UINT8 *p_ssidLength) Summary: Sets the SSID for the specified Connection Profile ID. Description: Sets the SSID and SSID Length elements in the Connection Profile. Note that an Access Point can have either a visible or hidden SSID. If an Access Point uses a hidden SSID then an active scan must be used (see scanType field in the Connection Algorithm). Precondition: MACInit must be called first. Parameters: CpId - Connection Profile ID p_ssid - Pointer to the SSID string ssidLength - Number of bytes in the SSID Returns: None. Remarks: None. *****************************************************************************/ void WF_CPSetSsid(UINT8 CpId, UINT8 *p_ssid, UINT8 ssidLength) { WF_ASSERT(ssidLength <= WF_MAX_SSID_LENGTH); LowLevel_CPSetElement(CpId, /* CP ID */ WF_CP_ELEMENT_SSID, /* Element ID */ (UINT8 *)p_ssid, /* pointer to element data */ ssidLength); /* number of element data bytes */ }
/***************************************************************************** * FUNCTION: SendMgmtMsg * * RETURNS: error code * * PARAMS: p_header -- pointer to mgmt message header data * headerLength -- number of bytes in the header * will be written * p_data -- pointer to mgmt message data * dataLength -- number of byte of data * * NOTES: Sends a management message *****************************************************************************/ void SendMgmtMsg(UINT8 *p_header, UINT8 headerLength, UINT8 *p_data, UINT8 dataLength) { #if defined(__18CXX) static UINT32 startTickCount; static UINT32 maxAllowedTicks; #else UINT32 startTickCount; UINT32 maxAllowedTicks; #endif /* cannot send management messages while in WF_ProcessEvent() */ WF_ASSERT(!isInWFProcessEvent()); EnsureWFisAwake(); /* if a Rx Data packet is mounted that has not yet been processed */ if (GetRawWindowState(RAW_RX_ID) == WF_RAW_DATA_MOUNTED) { /* save it, so after mgmt response received it can be restored */ PushRawWindow(RAW_RX_ID); RestoreRxData = TRUE; } /* mounts a tx mgmt buffer on the MRF24W when data tx is done */ maxAllowedTicks = TICKS_PER_SECOND / 200; /* 5 ms timeout */ startTickCount = (UINT32)TickGet(); while (!WFisTxMgmtReady() ) { MACProcess(); /* DEBUG -- REMOVE AFTER FIGURE OUT WHY TIMING OUT (RARELY HAPPENS) */ if (TickGet() - startTickCount >= maxAllowedTicks) { /* force flags so WFisTxMgmtReady will return TRUE */ SetRawWindowState(RAW_TX_ID, WF_RAW_UNMOUNTED); RawWindowReady[RAW_TX_ID] = FALSE; } } /* write out management header */ RawSetByte(RAW_TX_ID, p_header, headerLength); /* write out data (if any) */ if (dataLength > 0) { RawSetByte(RAW_TX_ID, p_data, dataLength); } /* send mgmt msg to MRF24W */ SendRAWManagementFrame(headerLength + dataLength); }
/* ********************************************************************************************************* * WF_TxDataAllocateBuffer() * * Description : Allocates a Tx Data Packet buffer on the MRF24WB0M * * Argument(s) : txDataPacketLength - length, in bytes, of memory needed * * Return(s) : None * * Caller(s) : Application * * Notes: : (1) Allocates memory on the MRF24WB0M to hold a Tx Data Packet * * (2) Do not assume this function always succeeds. During busy periods the MRF24WB0M may not * have available memory until the previous Tx data packet has finished transmitting. * ********************************************************************************************************* */ void WF_TxDataAllocateBuffer(uint16_t txDataPacketLength) { /* Ensure the MRF24WB0M is awake (only applies if PS-Poll was enabled) */ EnsureWFisAwake(); if (!AllocateDataTxBuffer(txDataPacketLength)) { WF_ASSERT(false); } }
/***************************************************************************** * FUNCTION: RawSetByte * * RETURNS: None * * PARAMS: * rawId - RAW ID * pBuffer - Buffer containing bytes to write * length - number of bytes to read * * NOTES: Writes bytes to RAW window *****************************************************************************/ void RawSetByte(UINT16 rawId, UINT8 *pBuffer, UINT16 length) { UINT8 regId; WF_ASSERT(!isIndexOutOfBounds(rawId)); /* attempting to write past end of RAW buffer */ /* write data to raw window */ regId = g_RawDataReg[rawId]; WriteWFArray(regId, pBuffer, length); }
/******************************************************************************* Function: void WF_MulticastSetConfig(tWFMultiCastConfig *p_config); Summary: Sets a multicast address filter using one of the two multicast filters. Description: This function allows the application to configure up to two Multicast Address Filters on the MRF24W. If two active multicast filters are set up they are OR’d together – the MRF24W will receive and pass to the Host CPU received packets from either multicast address. The allowable values in p_config (tWFMultiCastConfig / WFMulticastConfigStruct) are: * filterId -- WF_MULTICAST_FILTER_1 or WF_MULTICAST_FILTER_2 * action -- WF_MULTICAST_DISABLE_ALL (default) The Multicast Filter discards all received multicast messages – they will not be forwarded to the Host PIC. The remaining fields in this structure are ignored. WF_MULTICAST_ENABLE_ALL The Multicast Filter forwards all received multicast messages to the Host PIC. The remaining fields in this structure are ignored. WF_MULTICAST_USE_FILTERS The MAC filter will be used and the remaining fields in this structure configure which Multicast messages are forwarded to the Host PIC. * macBytes -- Array containing the MAC address to filter on (using the destination address of each incoming 802.11 frame). Specific bytes with the MAC address can be designated as ‘don’t care’ bytes. See macBitMask. This field in only used if action = WF_MULTICAST_USE_FILTERS. * macBitMask -- A byte where bits 5:0 correspond to macBytes[5:0]. If the bit is zero then the corresponding MAC byte must be an exact match for the frame to be forwarded to the Host PIC. If the bit is one then the corresponding MAC byte is a ‘don’t care’ and not used in the Multicast filtering process. This field in only used if action = WF_MULTICAST_USE_FILTERS. By default, both Multicast Filters are inactive. Example -- Filter on Multicast Address of 01:00:5e:xx:xx:xx where xx are don't care bytes. p_config->filterId = WF_MULTICAST_FILTER_1 [0] [1] [2] [3] [4] [5] p_config->macBytes[] = 01, 00, 5e, ff, ff, ff (0xff are the don't care bytes) p_config->macBitMask = 0x38 --> bits 5:3 = 1 (don't care on bytes 3,4,5) --> bits 2:0 = 0 (exact match required on bytes 0,1,2) Precondition: MACInit must be called first. Parameters: p_config -- pointer to the multicast config structure. See documentation. Returns: None. Remarks: Definition WF_USE_MULTICAST_FUNCTIONS needs to be enabled. *****************************************************************************/ void WF_MulticastSetConfig(tWFMultiCastConfig *p_config) { tMulticastFilterMsg msg; uint8_t filterId; filterId = p_config->filterId; WF_ASSERT(p_config->action <= WF_MULTICAST_USE_FILTERS); /* if want no multicast messages forwarded to the host PIC */ if (p_config->action == WF_MULTICAST_DISABLE_ALL) { msg.filterId = WF_MULTICAST_FILTER_1; msg.filterAction = ADDRESS_FILTER_DEACTIVATE; memset(msg.macAddress, 0xff, WF_MAC_ADDRESS_LENGTH); msg.macBitMask = 0x00; /* don't care */ } /* else if want all multicast messages forwarded to the host PIC */ else if (p_config->action == WF_MULTICAST_ENABLE_ALL) { msg.filterId = WF_MULTICAST_FILTER_1; msg.filterAction = MULTICAST_ADDRESS; memcpy((void *)msg.macAddress, (void *)p_config->macBytes, WF_MAC_ADDRESS_LENGTH); msg.macBitMask = 0x3f; /* don't care from host, but MRF24WG needs to see this bitmask */ } /* else if want a single multicast address or group of multicast addresses forwarded to Host PIC */ else if (p_config->action == WF_MULTICAST_USE_FILTERS) { msg.filterId = filterId; msg.filterAction = MULTICAST_ADDRESS; memcpy((void *)&msg.macAddress, (void *)p_config->macBytes, WF_MAC_ADDRESS_LENGTH); msg.macBitMask = p_config->macBitMask; } /* invalid action */ else { WF_ASSERT(false); } SendSetParamMsg(PARAM_COMPARE_ADDRESS, (uint8_t *)&msg, sizeof(msg) ); }
/***************************************************************************** Function: void DeallocateDataRxBuffer(void) Summary: Deallocates a Data Rx buffer Description: Typically called by MACGetHeader(), the assumption being that when the stack is checking for a newly received data message it is finished with the previously received data message. Also called by MACGetHeader() if the SNAP header is invalid and the packet is thrown away. Precondition: None Parameters: None Returns: None Remarks: None *****************************************************************************/ void DeallocateDataRxBuffer(void) { WF_ASSERT(GetRawWindowState(RAW_DATA_RX_ID) == WF_RAW_DATA_MOUNTED); /* perform deallocation of raw rx buffer */ RawMove(RAW_DATA_RX_ID, RAW_DATA_POOL, FALSE, 0); /* set state flag */ SetRawWindowState(RAW_DATA_RX_ID, WF_RAW_UNMOUNTED); /* the current length of the Rx data packet is now 0 (used by MAC) */ SetRxDataPacketLength(0); }
/***************************************************************************** * FUNCTION: WF_Init * * RETURNS: None * * PARAMS: * N/A. * * * NOTES: This function must be called once prior to calling any other WF... * functions. This function initializes the Wifi Driver internal State. * It also verifies functionality of the lower level SPI driver and * connected hardware. *****************************************************************************/ void WF_Init(void) { tWFDeviceInfo deviceInfo; WFHardwareInit(); RawInit(); WFEnableMRF24WB0MMode(); WF_GetDeviceInfo(&deviceInfo); // if MRF24WB #if !defined(MRF24WG) WF_ASSERT(deviceInfo.romVersion == 0x12); WF_ASSERT(deviceInfo.patchVersion >= 0x02); if (deviceInfo.romVersion == 0x12 && deviceInfo.patchVersion >= 0x09) { gRFModuleVer1209orLater = TRUE; } #else // must be a MRF24WG WF_ASSERT(deviceInfo.romVersion == 0x30 || deviceInfo.romVersion == 0x31); #endif /* send init messages to MRF24W */ WF_LibInitialize(); #if defined(WF_CONSOLE) WFConsoleInit(); #if defined(WF_CONSOLE_DEMO) IperfAppInit(); #endif #endif if(DHCPIsEnabled(0)) { SetDhcpProgressState(); } }
/******************************************************************************* Function: void SendMgmtMsg(UINT8 *p_header, UINT8 headerLength, UINT8 *p_data, UINT8 dataLength) Summary: Sends a management message to MRF24W. Description: Allocates management buffer on MRF24W. Then sends the management message (header + data) to MRF24W. Precondition: MACInit must be called. Parameters: p_header -- pointer to mgmt message header data headerLength -- number of bytes in the header will be written p_data -- pointer to mgmt message data dataLength -- number of bytes of data Returns: None Remarks: *****************************************************************************/ void SendMgmtMsg(UINT8 *p_header, UINT8 headerLength, UINT8 *p_data, UINT8 dataLength) { UINT32 timeoutPeriod; UINT32 startTickCount; /* cannot send management messages while in WF_ProcessEvent() */ WF_ASSERT(!isInWFProcessEvent()); EnsureWFisAwake(); /* Allocate a management buffer on the WiFi device. May have to wait a bit while the previous Data Tx packet is being sent */ /* which will free up the memory for this mgmt packet. */ timeoutPeriod = TICKS_PER_SECOND / 2; /* 500 ms */ startTickCount = (UINT32)TickGet(); while (AllocateMgmtTxBuffer(WF_MAX_TX_MGMT_MSG_SIZE) == FALSE) { if (TickGet() - startTickCount >= timeoutPeriod) { WF_ASSERT(FALSE); } } /* write out management header */ RawSetByte(RAW_MGMT_TX_ID, p_header, headerLength); /* write out data (if any) */ if (dataLength > 0) { RawSetByte(RAW_MGMT_TX_ID, p_data, dataLength); } /* send mgmt msg to MRF24W */ SendRAWManagementFrame(headerLength + dataLength); }
/******************************************************************************* Function: void WF_TxPowerSetMax(int8_t maxTxPower) Summary: Sets the Tx max power on the MRF24WG0MA/B. Description: After initialization the MRF24WG0MA/B max Tx power is determined by a factory-set value. This function can set a different maximum Tx power levels. However, this function can never set a maximum Tx power greater than the factory-set value, which can be read via WF_TxPowerGetFactoryMax(). Precondition: MACInit must be called first. Parameters: maxTxPower - valid range (0 to 18 dBm) Returns: None. Remarks: No conversion of units needed, input to MRF24WG0MA/B is in dBm. *****************************************************************************/ void WF_TxPowerSetMax(int8_t maxTxPower) { int8_t factoryMaxPower; uint8_t msgData[2]; int16_t max = (int16_t)maxTxPower; WF_TxPowerGetFactoryMax(&factoryMaxPower); WF_ASSERT(maxTxPower <= factoryMaxPower); /* cannot set max tx power greater than factor-set max tx power */ msgData[0] = (int8_t)(max >> 8); /* msb of max power */ msgData[1] = (int8_t)(max & 0xff); /* lsb of max power */ SendSetParamMsg(PARAM_TX_POWER, msgData, sizeof(msgData)); }
/******************************************************************************* Function: void WF_TxPowerSetMinMax(int8_t minTxPower, int8_t maxTxPower) Summary: Sets the Tx min and max power on the MRF24WB0MA/B. Description: After initialization the MRF24WB0MA/B max Tx power is determined by a factory-set value. This function can set a different minimum and maximum Tx power levels. However, this function can never set a maximum Tx power greater than the factory-set value, which can be read via WF_TxPowerGetFactoryMax(). Precondition: MACInit must be called first. Parameters: minTxPower - Desired minTxPower (-10 to 10dB) maxTxPower - Desired maxTxPower (-10 to 10dB) Returns: None. Remarks: No conversion of units needed, input to MRF24WB0MA/B is in dB. *****************************************************************************/ void WF_TxPowerSetMinMax(int8_t minTxPower, int8_t maxTxPower) { int8_t factoryMaxPower; uint8_t msgData[4]; /* need to input to chip two signed 16-bit values, max power followed by min power */ int16_t max; int16_t min; max = (int16_t)maxTxPower; min = (int16_t)minTxPower; WF_ASSERT(minTxPower <= maxTxPower); WF_TxPowerGetFactoryMax(&factoryMaxPower); WF_ASSERT(maxTxPower <= factoryMaxPower); /* cannot set max tx power greater than factor-set max tx power */ msgData[0] = (int8_t)(max >> 8); /* msb of max power */ msgData[1] = (int8_t)(max & 0xff); /* lsb of max power */ msgData[2] = (int8_t)(min >> 8); /* msb of min power */ msgData[3] = (int8_t)(min & 0xff); /* lsb of min power */ SendSetParamMsg(PARAM_TX_POWER, msgData, sizeof(msgData)); }
/******************************************************************************* Function: void WF_TxPowerSetMax(INT8 maxTxPower) Summary: Sets the Tx max power on the MRF24WG0M. Description: After initialization the MRF24WG0M max Tx power is determined by a factory-set value. This function can set a different maximum Tx power levels. However, this function can never set a maximum Tx power greater than the factory-set value, which can be read via WF_TxPowerGetFactoryMax(). Precondition: MACInit must be called first. Parameters: maxTxPower - valid range (0 to 18 dBm) Returns: None. Remarks: No conversion of units needed, input to MRF24WG0M is in dBm. *****************************************************************************/ void WF_TxPowerSetMax(INT8 maxTxPower) { INT8 factoryMaxPower; UINT8 msgData[2]; INT16 max = (INT16)maxTxPower; WF_TxPowerGetFactoryMax(&factoryMaxPower); WF_ASSERT(maxTxPower <= factoryMaxPower); /* cannot set max tx power greater than factor-set max tx power */ msgData[0] = (INT8)(max >> 8); /* msb of max power */ msgData[1] = (INT8)(max & 0xff); /* lsb of max power */ SendSetParamMsg(PARAM_TX_POWER, msgData, sizeof(msgData)); }