/***************************************************************************** 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; } }
bool AllocateDataTxBuffer(uint16_t bytesNeeded) { uint16_t bufAvail; uint16_t byteCount; /* 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_TX_ID, RAW_DATA_POOL, true, bytesNeeded); SYS_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_DATA_MOUNTED); return true; }
/***************************************************************************** * 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; EnsureWFisAwake(); 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; }
/* ********************************************************************************************************* * WF_RxDataDeallocateBuffer() * * Description : Releases the MRF24WB0M memory containing an Rx data packet after the application is done with * it. * * Argument(s) : None * * Return(s) : None * * Caller(s) : Application * * Notes: : (1) Must be called after the application completes processing of an Rx data packet. * ********************************************************************************************************* */ void WF_RxDataDeallocateBuffer(void) { /* Ensure the MRF24WB0M is awake (only applies if PS-Poll was enabled) */ EnsureWFisAwake(); DeallocateDataRxBuffer(); }
/***************************************************************************** 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) { EnsureWFisAwake(); /* perform deallocation of raw rx buffer */ RawMove(RAW_DATA_RX_ID, RAW_DATA_POOL, false, 0); }
/* ********************************************************************************************************* * 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); }
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: 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: WFProcess * * RETURNS: None * * PARAMS: None * * NOTES: This function is called from WFProcess. It does the following: * 1) checks for and processes MRF24WB0M external interrupt events * 2) checks for and processes received management messages from the MRF24WB0M * 3) maintains the PS-Poll state (if applicable) * *****************************************************************************/ void WFProcess(void) { UINT16 len; //---------------------------------------------------------- // if there is a MRF24WB0M External interrupt (EINT) to process //---------------------------------------------------------- if (g_ExIntNeedsServicing == TRUE) { g_ExIntNeedsServicing = FALSE; ProcessInterruptServiceResult(); } //---------------------------------------- // else if there is management msg to read //---------------------------------------- else if (g_MgmtReadMsgReady == TRUE) { /* Ensure the MRF24WB0M is awake (only applies if PS-Poll was enabled) */ EnsureWFisAwake(); //----------------------------- // process management read //----------------------------- // if the Raw Rx buffer is available, or only has the scratch mounted, then mount it so // we can process received Mgmt message. Otherwise, stay in this state and keep checking // until we can mount the Raw Rx buffer and get the management message. Once the Raw Rx // is acquired, rx data packets are held off until we finish processing mgmt message. if ( RawGetMgmtRxBuffer(&len) ) { // handle received managment message g_MgmtReadMsgReady = FALSE; ProcessMgmtRxMsg(); // reenable interrupts WF_EintEnable(); } } //----------------------------------- // else no EINT or Mgmt Rx to process //----------------------------------- else { #if defined (WF_USE_POWER_SAVE_FUNCTIONS) /* if PS-Poll mode was enabled by application and was previously deactivated by WF driver */ if (WFisPsPollEnabled() && !WFIsPsPollActive() ) { /* reactivate PS-Poll mode on MRF24WB0M (allow MRF24WB0M to sleep) */ WFConfigureLowPowerMode(WF_LOW_POWER_MODE_ON); } #endif } }
/* ********************************************************************************************************* * WF_TxDataSendPacket() * * Description : Directs the MRF24WB0M to transmit a Tx data packet to the 802.11 network. * * Argument(s) : length - length, in bytes, of data packet * * Return(s) : Error code * * Caller(s) : Application * * Notes: : (1) MRF24WB0M Tx data block must first be allocated via WF_TxDataAllocateBuffer() * * (2) Current support only for full length Tx data messaages. In other words, startIndex * must be 0, and length must be the total length of the Tx data packet. * ********************************************************************************************************* */ void WF_TxDataSendPacket(uint16_t length) { tTxDataPreamble txPreamble; /* fill in tx data preamble with correct header */ txPreamble.type = WF_DATA_REQUEST_TYPE; txPreamble.subType = WF_STD_DATA_MSG_SUBTYPE; txPreamble.h2 = 1; txPreamble.h3 = 0; /* Ensure the MRF24WB0M is awake (only applies if PS-Poll was enabled) */ EnsureWFisAwake(); /* write out preamble to MRF24WB0M buffer to the two extra bytes at start of allocated buffer */ RawSetIndex(RAW_TX_ID, 0); WriteWFArray(RAW_1_DATA_REG, (uint8_t *)&txPreamble, WF_SIZE_OF_TX_DATA_PREAMBLE ); /* now tell MRF24WB0M to transmit the tx data packet */ RawSendTxBuffer(length); }
/* ********************************************************************************************************* * WF_TxDataWrite() * * Description : Writes Tx packet data from Host CPU to MRF24WB0M tx buffer * * Argument(s) : p_txData - Pointer to Tx data * length - length, in bytes, of Tx data * startIndex - Index within MRF24WB0M Tx data block to start writing * * Return(s) : None * * Caller(s) : Application * * Notes: : (1) MRF24WB0M Tx data block must first be allocated via WF_TxDataAllocateBuffer() * * (2) Current support only for full length Tx data messaages. In other words, startIndex * must be 0, and length must be the total length of the Tx data packet. * ********************************************************************************************************* */ void WF_TxDataWrite(uint8_t *p_txData, uint16_t length, uint16_t startIndex) { WF_ASSERT(startIndex == 0); if (length == 0) { return; } /* Ensure the MRF24WB0M is awake (only applies if PS-Poll was enabled) */ EnsureWFisAwake(); /* set the RAW index to desired location, offset by the Tx data preamble */ RawSetIndex(RAW_TX_ID, startIndex + WF_SIZE_OF_TX_DATA_PREAMBLE); /* write tx data to chip */ WriteWFArray(RAW_1_DATA_REG, p_txData, length); }
/******************************************************************************* 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: WFProcess * * RETURNS: None * * PARAMS: None * * NOTES: This function is called from WFProcess. It does the following: * 1) checks for and processes MRF24WB0M external interrupt events * 2) checks for and processes received management messages from the MRF24WB0M * 3) maintains the PS-Poll state (if applicable) * *****************************************************************************/ void WFProcess(void) { UINT16 len; //---------------------------------------------------------- // if there is a MRF24WB0M External interrupt (EINT) to process //---------------------------------------------------------- if (g_ExIntNeedsServicing == TRUE) { g_ExIntNeedsServicing = FALSE; ProcessInterruptServiceResult(); } //---------------------------------------- // else if there is management msg to read //---------------------------------------- else if (g_MgmtReadMsgReady == TRUE) { /* Ensure the MRF24WB0M is awake (only applies if PS-Poll was enabled) */ EnsureWFisAwake(); //----------------------------- // process management read //----------------------------- // if the Raw Rx buffer is available, or only has the scratch mounted, then mount it so // we can process received Mgmt message. Otherwise, stay in this state and keep checking // until we can mount the Raw Rx buffer and get the management message. Once the Raw Rx // is acquired, rx data packets are held off until we finish processing mgmt message. if ( RawGetMgmtRxBuffer(&len) ) { // handle received managment message g_MgmtReadMsgReady = FALSE; ProcessMgmtRxMsg(); // reenable interrupts WF_EintEnable(); } } }
/***************************************************************************** Function: bool AllocateDataTxBuffer(uint16_t 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_t bytesNeeded) { uint16_t bufAvail; /* 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 ) { RawMove(RAW_DATA_TX_ID, RAW_DATA_POOL, true, bytesNeeded); return true; } /* else not enough bytes available at this time to satisfy request */ else { ////SYS_CONSOLE_MESSAGE("NB\r\n"); return false; } }
/***************************************************************************** * FUNCTION: ProcessInterruptServiceResult * * RETURNS: N/A * * PARAMS: * N/A * * * NOTES: Processes EXINT from MRF24WB0M. Called by WFProcess(). *****************************************************************************/ static void ProcessInterruptServiceResult(void) { UINT8 hostIntRegValue; UINT8 hostIntMaskRegValue; UINT8 hostInt; /* Ensure the MRF24WB0M stays awake (only applies if PS-Poll was enabled) */ EnsureWFisAwake(); /* read hostInt register to determine cause of interrupt */ hostIntRegValue = Read8BitWFRegister(WF_HOST_INTR_REG); // OR in the saved interrupts during the time when we were waiting for raw complete, set by WFEintHandler() hostIntRegValue |= g_HostIntSaved; // done with the saved interrupts, clear variable g_HostIntSaved = 0; hostIntMaskRegValue = Read8BitWFRegister(WF_HOST_MASK_REG); // AND the two registers together to determine which active, enabled interrupt has occurred hostInt = hostIntRegValue & hostIntMaskRegValue; // if received a level 2 interrupt (should not happen!) if((hostInt & WF_HOST_INT_MASK_INT2) == WF_HOST_INT_MASK_INT2) { /* read the 16 bit interrupt register */ /* CURRENTLY unhandled interrupt */ WF_ASSERT(FALSE); WF_EintEnable(); } // else if got a FIFO 1 Threshold interrupt (Management Fifo) else if((hostInt & WF_HOST_INT_MASK_FIFO_1_THRESHOLD) == WF_HOST_INT_MASK_FIFO_1_THRESHOLD) { /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, WF_HOST_INT_MASK_FIFO_1_THRESHOLD); // notify MAC state machine that management message needs to be processed g_MgmtReadMsgReady = TRUE; } // else if got a FIFO 0 Threshold Interrupt (Data Fifo) else if((hostInt & WF_HOST_INT_MASK_FIFO_0_THRESHOLD) == WF_HOST_INT_MASK_FIFO_0_THRESHOLD) { /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, WF_HOST_INT_MASK_FIFO_0_THRESHOLD); g_HostRAWDataPacketReceived = TRUE; /* this global flag is used in MACGetHeader() to determine a received data packet */ #if defined(WF_USE_DATA_TX_RX_FUNCTIONS) { UINT16 rxDataPacketLength; /* determine length of packet and signal the rx data packet event */ rxDataPacketLength = Read16BitWFRegister(WF_HOST_RFIFO_BCNT0_REG) & 0x0fff; /* LS 12 bits are the data length */ WF_ProcessEvent(WF_EVENT_RX_PACKET_RECEIVED, rxDataPacketLength); } #endif } // else got a Host interrupt that we don't handle else if(hostInt) { /* unhandled interrupt */ /* clear this interrupt */ Write8BitWFRegister(WF_HOST_INTR_REG, hostInt); WF_EintEnable(); } // we got a spurious interrupt (no bits set in register) else { /* spurious interrupt */ WF_EintEnable(); } }