void vCheckBuffersAndQueue( void ) { static UBaseType_t uxLastMinBufferCount = 0; #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 ) static UBaseType_t uxLastMinQueueSpace; #endif static UBaseType_t uxCurrentCount; #if( ipconfigCHECK_IP_QUEUE_SPACE != 0 ) { uxCurrentCount = uxGetMinimumIPQueueSpace(); if( uxLastMinQueueSpace != uxCurrentCount ) { /* The logging produced below may be helpful while tuning +TCP: see how many buffers are in use. */ uxLastMinQueueSpace = uxCurrentCount; FreeRTOS_printf( ( "Queue space: lowest %lu\n", uxCurrentCount ) ); } } #endif /* ipconfigCHECK_IP_QUEUE_SPACE */ uxCurrentCount = uxGetMinimumFreeNetworkBuffers(); if( uxLastMinBufferCount != uxCurrentCount ) { /* The logging produced below may be helpful while tuning +TCP: see how many buffers are in use. */ uxLastMinBufferCount = uxCurrentCount; FreeRTOS_printf( ( "Network buffers: %lu lowest %lu\n", uxGetNumberOfFreeNetworkBuffers(), uxCurrentCount ) ); } }
void FreeRTOS_PrintARPCache( void ) { BaseType_t x, xCount = 0; /* Loop through each entry in the ARP cache. */ for( x = 0; x < ipconfigARP_CACHE_ENTRIES; x++ ) { if( xARPCache[ x ].ulIPAddress != 0ul && xARPCache[ x ].ucAge > 0U ) { /* See if the MAC-address also matches, and we're all happy */ FreeRTOS_printf( ( "Arp %2ld: %3u - %16lxip : %02x:%02x:%02x : %02x:%02x:%02x\n", x, xARPCache[ x ].ucAge, xARPCache[ x ].ulIPAddress, xARPCache[ x ].xMACAddress.ucBytes[0], xARPCache[ x ].xMACAddress.ucBytes[1], xARPCache[ x ].xMACAddress.ucBytes[2], xARPCache[ x ].xMACAddress.ucBytes[3], xARPCache[ x ].xMACAddress.ucBytes[4], xARPCache[ x ].xMACAddress.ucBytes[5] ) ); xCount++; } } FreeRTOS_printf( ( "Arp has %ld entries\n", xCount ) ); }
void vStartNTPTask( uint16_t usTaskStackSize, UBaseType_t uxTaskPriority ) { /* The only public function in this module: start a task to contact some NTP server. */ if( xNTPTaskhandle != NULL ) { switch( xStatus ) { case EStatusPause: xStatus = EStatusAsking; vSignalTask(); break; case EStatusLookup: FreeRTOS_printf( ( "NTP looking up server\n" ) ); break; case EStatusAsking: FreeRTOS_printf( ( "NTP still asking\n" ) ); break; case EStatusFailed: FreeRTOS_printf( ( "NTP failed somehow\n" ) ); ulIPAddressFound = 0ul; xStatus = EStatusLookup; vSignalTask(); break; } } else { xUDPSocket = FreeRTOS_socket( FREERTOS_AF_INET, FREERTOS_SOCK_DGRAM, FREERTOS_IPPROTO_UDP ); if( xUDPSocket != NULL ) { struct freertos_sockaddr xAddress; #if( ipconfigUSE_CALLBACKS != 0 ) BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 0 ); #else BaseType_t xReceiveTimeOut = pdMS_TO_TICKS( 5000 ); #endif xAddress.sin_addr = 0ul; xAddress.sin_port = FreeRTOS_htons( NTP_PORT ); FreeRTOS_bind( xUDPSocket, &xAddress, sizeof( xAddress ) ); FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_RCVTIMEO, &xReceiveTimeOut, sizeof( xReceiveTimeOut ) ); xTaskCreate( prvNTPTask, /* The function that implements the task. */ ( const char * ) "NTP client", /* Just a text name for the task to aid debugging. */ usTaskStackSize, /* The stack size is defined in FreeRTOSIPConfig.h. */ NULL, /* The task parameter, not used in this case. */ uxTaskPriority, /* The priority assigned to the task is defined in FreeRTOSConfig.h. */ &xNTPTaskhandle ); /* The task handle. */ } else { FreeRTOS_printf( ( "Creating socket failed\n" ) ); } } }
static BaseType_t prvProcessCmd( xHTTPClient *pxClient, BaseType_t xIndex ) { BaseType_t xResult = 0; /* A new command has been received. Process it */ switch( xIndex ) { case ECMD_GET: xResult = prvOpenUrl( pxClient ); break; case ECMD_HEAD: case ECMD_POST: case ECMD_PUT: case ECMD_DELETE: case ECMD_TRACE: case ECMD_OPTIONS: case ECMD_CONNECT: case ECMD_PATCH: case ECMD_UNK: { FreeRTOS_printf( ( "prvProcessCmd: Not implemented: %s\n", xWebCommands[xIndex].pcCommandName ) ); } break; } return xResult; }
static void start_test(unsigned test) { if (test < TEST_COUNT) { FreeRTOS_printf(("Creating a task for test %d\n", test)); if (pdPASS != xTaskCreate( single_test_runner, "single test", SINGLE_TEST_STACK_DEPTH, (void*)test, SINGLE_TEST_PRIORITY, &m_aTest[test].task )) { FreeRTOS_printf(("\n!! Failed to create a task for test %d!\n", test)); } } }
static void probePHY(ETH_HandleTypeDef * heth) { uint32_t ulRegValue = 0; /* Read the result of the auto-negotiation. */ HAL_ETH_ReadPHYRegister(heth, PHY_SR, &ulRegValue); if (heth->Init.AutoNegotiation != ETH_AUTONEGOTIATION_DISABLE) { /* Read the result of the auto-negotiation. */ HAL_ETH_ReadPHYRegister(heth, PHY_SR, &ulRegValue); if ((ulRegValue & PHY_LINK_STATUS) != 0) { ulPHYLinkStatus |= BMSR_LINK_STATUS; } else { ulPHYLinkStatus &= ~( BMSR_LINK_STATUS); } FreeRTOS_printf( ( ">> Autonego ready: %08x: %s duplex %u mbit %s status\n", (unsigned int)ulRegValue, (ulRegValue & PHY_DUPLEX_STATUS) ? "full" : "half", (ulRegValue & PHY_SPEED_STATUS) ? 10 : 100, (ulRegValue & PHY_LINK_STATUS) ? "high" : "low" ) ); } }
static void passEthMessages( void ) { IPStackEvent_t xRxEvent; xRxEvent.eEventType = eNetworkRxEvent; xRxEvent.pvData = ( void * ) ethMsg; if( xSendEventStructToIPTask( &xRxEvent, ( portTickType ) 1000 ) != pdPASS ) { /* The buffer could not be sent to the stack so must be released again. This is a deferred handler taskr, not a real interrupt, so it is ok to use the task level function here. */ do { NetworkBufferDescriptor_t *xNext = ethMsg->pxNextBuffer; vReleaseNetworkBufferAndDescriptor( ethMsg ); ethMsg = xNext; } while( ethMsg != NULL ); iptraceETHERNET_RX_EVENT_LOST(); FreeRTOS_printf( ( "passEthMessages: Can not queue return packet!\n" ) ); } ethMsg = ethLast = NULL; }
void emacps_check_tx( xemacpsif_s *xemacpsif ) { int tail = xemacpsif->txTail; int head = xemacpsif->txHead; if( head != tail ) { for( ; ; ) { if( ( xemacpsif->txSegments[ tail ].flags & XEMACPS_TXBUF_USED_MASK ) == 0 ) { /* The driver is still waiting for the EMAC to sent this message. When done, "TXBUF_USED" will be set. */ break; } #if( ipconfigZERO_COPY_TX_DRIVER != 0 ) #warning ipconfigZERO_COPY_TX_DRIVER is defined { void *pvBuffer = pxDMA_tx_buffers[ tail ]; NetworkBufferDescriptor_t *pxBuffer; if( pvBuffer != NULL ) { pxDMA_tx_buffers[ tail ] = NULL; pxBuffer = pxPacketBuffer_to_NetworkBuffer( pvBuffer ); if( pxBuffer != NULL ) { vReleaseNetworkBufferAndDescriptor( pxBuffer ); } else { FreeRTOS_printf( ( "emacps_check_tx: Can not find network bufffer" ) ); } } } #endif /* Clear all but the "used" and "wrap" bits. */ if( tail < ipconfigNIC_N_TX_DESC - 1 ) { xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK; } else { xemacpsif->txSegments[ tail ].flags = XEMACPS_TXBUF_USED_MASK | XEMACPS_TXBUF_WRAP_MASK; } if( ++tail == ipconfigNIC_N_TX_DESC ) { tail = 0; } if( tail == head ) { break; } } xemacpsif->txTail = tail; } return; }
void StartPubnubTask(uint16_t usTaskStackSize, UBaseType_t uxTaskPriority) { m_TestResultQueue = xQueueCreate(g_max_conc_tests + 2, sizeof(struct TestResultMessage)); if (0 == m_TestResultQueue) { FreeRTOS_printf(("\n!! Failed to create the test result queue!\n")); } if (pdPASS != xTaskCreate( test_runner, "test runner", usTaskStackSize, NULL, uxTaskPriority, NULL )) { vQueueDelete(m_TestResultQueue); FreeRTOS_printf(("\n!! Failed to create the task runner!\n")); } }
static void prvFileClose( xHTTPClient *pxClient ) { if( pxClient->pxFileHandle != NULL ) { FreeRTOS_printf( ( "Closing file: %s\n", pxClient->pcCurrentFilename ) ); ff_fclose( pxClient->pxFileHandle ); pxClient->pxFileHandle = NULL; } }
void test_runner(void *arg) { PUBNUB_UNUSED(arg); for (;;) { unsigned next_test = 0; unsigned failed_count = 0; unsigned passed_count = 0; unsigned indete_count = 0; unsigned tests_in_progress = 0; FreeRTOS_printf(("Starting Run of %d tests\n", TEST_COUNT)); while (failed_count + passed_count + indete_count < TEST_COUNT) { struct TestResultMessage msg; if ((tests_in_progress < g_max_conc_tests) && (next_test < TEST_COUNT)) { start_test(next_test++); ++tests_in_progress; } if (pdTRUE == xQueueReceive(m_TestResultQueue, &msg, pdMS_TO_TICKS(20))) { switch (msg.result) { case trFail: FreeRTOS_printf(("\n !!!!!!! The %d. test ('%s') failed!\n\n", msg.test + 1, m_aTest[msg.test].name)); ++failed_count; break; case trPass: ++passed_count; break; case trIndeterminate: ++indete_count; FreeRTOS_printf((" Indeterminate %d. test ('%s') of %d\t", msg.test+1, m_aTest[msg.test].name, TEST_COUNT)); /* Should restart the test... */ //FreeRTOS_printf((" ReStarting %d. test of %ld\t", msg.test + 1, TEST_COUNT)); break; } #ifdef INCLUDE_vTaskDelete vTaskDelete(m_aTest[msg.test].task); #endif --tests_in_progress; } } FreeRTOS_printf(("Test run over.\n")); if (passed_count == TEST_COUNT) { FreeRTOS_printf(("\n All %d tests passed\n", TEST_COUNT)); } else { FreeRTOS_printf(("\n\n %d tests passed, %d tests failed, %d tests indeterminate\n", passed_count, failed_count, indete_count )); } vTaskDelay(pdMS_TO_TICKS(10 * 1000)); } }
BaseType_t xPhyCheckLinkStatus( EthernetPhy_t *pxPhyObject, BaseType_t xHadReception ) { uint32_t ulStatus, ulBitMask = 1u; BaseType_t xPhyIndex; BaseType_t xNeedCheck = pdFALSE; if( xHadReception > 0 ) { /* A packet was received. No need to check for the PHY status now, but set a timer to check it later on. */ vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) ); pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS ); } else if( xTaskCheckForTimeOut( &( pxPhyObject->xLinkStatusTimer ), &( pxPhyObject->xLinkStatusRemaining ) ) != pdFALSE ) { for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 ) { BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ]; if( pxPhyObject->fnPhyRead( xPhyAddress, phyREG_01_BMSR, &ulStatus ) == 0 ) { if( !!( pxPhyObject->ulLinkStatusMask & ulBitMask ) != !!( ulStatus & phyBMSR_LINK_STATUS ) ) { if( ( ulStatus & phyBMSR_LINK_STATUS ) != 0 ) { pxPhyObject->ulLinkStatusMask |= ulBitMask; } else { pxPhyObject->ulLinkStatusMask &= ~( ulBitMask ); } FreeRTOS_printf( ( "xPhyCheckLinkStatus: PHY LS now %02lX\n", pxPhyObject->ulLinkStatusMask ) ); eventLogAdd( "PHY LS now %02lX", pxPhyObject->ulLinkStatusMask ); xNeedCheck = pdTRUE; } } } vTaskSetTimeOutState( &( pxPhyObject->xLinkStatusTimer ) ); if( ( pxPhyObject->ulLinkStatusMask & phyBMSR_LINK_STATUS ) != 0 ) { pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_HIGH_CHECK_TIME_MS ); } else { pxPhyObject->xLinkStatusRemaining = pdMS_TO_TICKS( ipconfigPHY_LS_LOW_CHECK_TIME_MS ); } } return xNeedCheck; }
static BaseType_t xGMACWaitLS( TickType_t xMaxTime ) { TickType_t xStartTime = xTaskGetTickCount(); TickType_t xEndTime; BaseType_t xReturn; const TickType_t xShortTime = pdMS_TO_TICKS( 100UL ); for( ;; ) { xEndTime = xTaskGetTickCount(); if( ( xEndTime - xStartTime ) > xMaxTime ) { /* Wated more than xMaxTime, return. */ xReturn = pdFALSE; break; } /* Check the link status again. */ ulPHYLinkStatus = ulReadMDIO( PHY_REG_01_BMSR ); if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) { /* Link is up - return. */ xReturn = pdTRUE; break; } /* Link is down - wait in the Blocked state for a short while (to allow other tasks to execute) before checking again. */ vTaskDelay( xShortTime ); } FreeRTOS_printf( ( "xGMACWaitLS: %ld (PHY %d) freq %lu Mz\n", xReturn, ethernet_phy_addr, sysclk_get_cpu_hz() / HZ_PER_MHZ ) ); return xReturn; }
static BaseType_t prvOpenUrl( xHTTPClient *pxClient ) { BaseType_t xRc; char pcSlash[ 2 ]; pxClient->bits.ulFlags = 0; if( pxClient->pcUrlData[ 0 ] != '/' ) { /* Insert a slah before the file name */ pcSlash[ 0 ] = '/'; pcSlash[ 1 ] = '\0'; } else { /* The browser provided a starting '/' already */ pcSlash[ 0 ] = '\0'; } snprintf( pxClient->pcCurrentFilename, sizeof pxClient->pcCurrentFilename, "%s%s%s", pxClient->pcRootDir, pcSlash, pxClient->pcUrlData); pxClient->pxFileHandle = ff_fopen( pxClient->pcCurrentFilename, "rb" ); FreeRTOS_printf( ( "Open file '%s': %s\n", pxClient->pcCurrentFilename, pxClient->pxFileHandle != NULL ? "Ok" : strerror( stdioGET_ERRNO() ) ) ); if( pxClient->pxFileHandle == NULL ) { xRc = prvSendReply( pxClient, WEB_NOT_FOUND ); /* "404 File not found" */ } else { pxClient->xBytesLeft = pxClient->pxFileHandle->ulFileSize; xRc = prvSendFile( pxClient ); } return xRc; }
/* Discover all PHY's connected by polling 32 indexes ( zero-based ) */ BaseType_t xPhyDiscover( EthernetPhy_t *pxPhyObject ) { BaseType_t xPhyAddress; pxPhyObject->xPortCount = 0; for( xPhyAddress = phyMIN_PHY_ADDRESS; xPhyAddress <= phyMAX_PHY_ADDRESS; xPhyAddress++ ) { uint32_t ulLowerID; pxPhyObject->fnPhyRead( xPhyAddress, phyREG_03_PHYSID2, &ulLowerID ); /* A valid PHY id can not be all zeros or all ones. */ if( ( ulLowerID != ( uint16_t )~0u ) && ( ulLowerID != ( uint16_t )0u ) ) { uint32_t ulUpperID; uint32_t ulPhyID; pxPhyObject->fnPhyRead( xPhyAddress, phyREG_02_PHYSID1, &ulUpperID ); ulPhyID = ( ( ( uint32_t ) ulUpperID ) << 16 ) | ( ulLowerID & 0xFFF0 ); pxPhyObject->ucPhyIndexes[ pxPhyObject->xPortCount ] = xPhyAddress; pxPhyObject->ulPhyIDs[ pxPhyObject->xPortCount ] = ulPhyID; pxPhyObject->xPortCount++; /* See if there is more storage space. */ if( pxPhyObject->xPortCount == ipconfigPHY_MAX_PORTS ) { break; } } } if( pxPhyObject->xPortCount > 0 ) { FreeRTOS_printf( ( "PHY ID %lX\n", pxPhyObject->ulPhyIDs[ 0 ] ) ); eventLogAdd( "PHY ID 0x%lX", pxPhyObject->ulPhyIDs[ 0 ] ); } return pxPhyObject->xPortCount; }
static void vDNS_callback( const char *pcName, void *pvSearchID, uint32_t ulIPAddress ) { char pcBuf[16]; /* The DNS lookup has a result, or it has reached the time-out. */ FreeRTOS_inet_ntoa( ulIPAddress, pcBuf ); FreeRTOS_printf( ( "IP address of %s found: %s\n", pcName, pcBuf ) ); if( ulIPAddressFound == 0ul ) { ulIPAddressFound = ulIPAddress; } /* For testing: in case DNS doen't respond, still try some NTP server with a known IP-address. */ if( ulIPAddressFound == 0ul ) { ulIPAddressFound = FreeRTOS_inet_addr_quick( 184, 105, 182, 7 ); /* ulIPAddressFound = FreeRTOS_inet_addr_quick( 103, 242, 70, 4 ); */ } xStatus = EStatusAsking; vSignalTask(); }
static BaseType_t prvOpenURL( HTTPClient_t *pxClient ) { BaseType_t xRc; char pcSlash[ 2 ]; pxClient->bits.ulFlags = 0; #if( ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK != 0 ) { if( strchr( pxClient->pcUrlData, ipconfigHTTP_REQUEST_CHARACTER ) != NULL ) { size_t xResult; xResult = uxApplicationHTTPHandleRequestHook( pxClient->pcUrlData, pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ) ); if( xResult > 0 ) { strcpy( pxClient->pxParent->pcContentsType, "text/html" ); snprintf( pxClient->pxParent->pcExtraContents, sizeof( pxClient->pxParent->pcExtraContents ), "Content-Length: %d\r\n", ( int ) xResult ); xRc = prvSendReply( pxClient, WEB_REPLY_OK ); /* "Requested file action OK" */ if( xRc > 0 ) { xRc = FreeRTOS_send( pxClient->xSocket, pxClient->pcCurrentFilename, xResult, 0 ); } /* Although against the coding standard of FreeRTOS, a return is done here to simplify this conditional code. */ return xRc; } } } #endif /* ipconfigHTTP_HAS_HANDLE_REQUEST_HOOK */ if( pxClient->pcUrlData[ 0 ] != '/' ) { /* Insert a slash before the file name. */ pcSlash[ 0 ] = '/'; pcSlash[ 1 ] = '\0'; } else { /* The browser provided a starting '/' already. */ pcSlash[ 0 ] = '\0'; } snprintf( pxClient->pcCurrentFilename, sizeof( pxClient->pcCurrentFilename ), "%s%s%s", pxClient->pcRootDir, pcSlash, pxClient->pcUrlData); pxClient->pxFileHandle = ff_fopen( pxClient->pcCurrentFilename, "rb" ); FreeRTOS_printf( ( "Open file '%s': %s\n", pxClient->pcCurrentFilename, pxClient->pxFileHandle != NULL ? "Ok" : strerror( stdioGET_ERRNO() ) ) ); if( pxClient->pxFileHandle == NULL ) { /* "404 File not found". */ xRc = prvSendReply( pxClient, WEB_NOT_FOUND ); } else { pxClient->uxBytesLeft = ( size_t ) pxClient->pxFileHandle->ulFileSize; xRc = prvSendFile( pxClient ); } return xRc; }
/* Send a reset commando to a set of PHY-ports. */ static uint32_t xPhyReset( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask ) { uint32_t ulDoneMask, ulConfig; TickType_t xRemainingTime; TimeOut_t xTimer; BaseType_t xPhyIndex; /* A bit-mask ofPHY ports that are ready. */ ulDoneMask = 0ul; /* Set the RESET bits high. */ for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ ) { BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ]; /* Read Control register. */ pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig ); pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulConfig | phyBMCR_RESET ); } xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( 1000UL ); vTaskSetTimeOutState( &xTimer ); /* The reset should last less than a second. */ for( ;; ) { for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ ) { BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ]; pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig ); if( ( ulConfig & phyBMCR_RESET ) == 0 ) { FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET %d ready\n", (int)xPhyIndex ) ); ulDoneMask |= ( 1ul << xPhyIndex ); } } if( ulDoneMask == ulPhyMask ) { break; } if( xTaskCheckForTimeOut( &xTimer, &xRemainingTime ) != pdFALSE ) { FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET timed out ( done 0x%02lX )\n", ulDoneMask ) ); break; } } /* Clear the reset bits. */ for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ ) { BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ]; pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig ); pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, ulConfig & ~phyBMCR_RESET ); } vTaskDelay( pdMS_TO_TICKS( 50ul ) ); eventLogAdd( "PHY reset %d ports", (int)pxPhyObject->xPortCount ); return ulDoneMask; }
BaseType_t xHTTPClientWork( xTCPClient *pxTCPClient ) { BaseType_t xRc; xHTTPClient *pxClient = ( xHTTPClient * ) pxTCPClient; if( pxClient->pxFileHandle != NULL ) { prvSendFile( pxClient ); } xRc = FreeRTOS_recv( pxClient->xSocket, ( void * )pcCOMMAND_BUFFER, sizeof( pcCOMMAND_BUFFER ), 0 ); if( xRc > 0 ) { BaseType_t xIndex; const char *pcEndOfCmd; const struct xWEB_COMMAND *curCmd; char *pcBuffer = pcCOMMAND_BUFFER; if( xRc < ( BaseType_t ) sizeof( pcCOMMAND_BUFFER ) ) { pcBuffer[ xRc ] = '\0'; } while( xRc && ( pcBuffer[ xRc - 1 ] == 13 || pcBuffer[ xRc - 1 ] == 10 ) ) { pcBuffer[ --xRc ] = '\0'; } pcEndOfCmd = pcBuffer + xRc; curCmd = xWebCommands; pxClient->pcUrlData = pcBuffer; /* Pointing to "/index.html HTTP/1.1" */ pxClient->pcRestData = pcEmptyString; /* Pointing to "HTTP/1.1" */ // Last entry is "ECMD_UNK" for( xIndex = 0; xIndex < WEB_CMD_COUNT - 1; xIndex++, curCmd++ ) { BaseType_t xLength; xLength = curCmd->xCommandLength; if( ( xRc >= xLength ) && ( memcmp( curCmd->pcCommandName, pcBuffer, xLength ) == 0 ) ) { char *pcLastPtr; pxClient->pcUrlData += xLength + 1; for( pcLastPtr = (char *)pxClient->pcUrlData; pcLastPtr < pcEndOfCmd; pcLastPtr++ ) { char ch = *pcLastPtr; if( ( ch == '\0' ) || ( strchr( "\n\r \t", ch ) != NULL ) ) { *pcLastPtr = '\0'; pxClient->pcRestData = pcLastPtr + 1; break; } } break; } } xRc = prvProcessCmd( pxClient, xIndex ); } else if( xRc < 0 ) { /* The connection will be closed and the client will be deleted */ FreeRTOS_printf( ( "xHTTPClientWork: rc = %ld\n", xRc ) ); } return xRc; }
BaseType_t xPhyStartAutoNegotiation( EthernetPhy_t *pxPhyObject, uint32_t ulPhyMask ) { uint32_t xPhyIndex, ulDoneMask, ulBitMask; uint32_t ulPHYLinkStatus, ulRegValue; TickType_t xRemainingTime; TimeOut_t xTimer; if( ulPhyMask == ( uint32_t )0u ) { return 0; } for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ ) { if( ( ulPhyMask & ( 1lu << xPhyIndex ) ) != 0lu ) { BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ]; /* Enable Auto-Negotiation. */ pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_04_ADVERTISE, pxPhyObject->ulACRValue); pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, pxPhyObject->ulBCRValue | phyBMCR_AN_RESTART ); } } eventLogAdd( "AN start" ); xRemainingTime = ( TickType_t ) pdMS_TO_TICKS( 3000UL ); vTaskSetTimeOutState( &xTimer ); ulDoneMask = 0; /* Wait until the auto-negotiation will be completed */ for( ;; ) { ulBitMask = ( uint32_t )1u; for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 ) { if( ( ulPhyMask & ulBitMask ) != 0lu ) { if( ( ulDoneMask & ulBitMask ) == 0lu ) { BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ]; pxPhyObject->fnPhyRead( xPhyAddress, phyREG_01_BMSR, &ulRegValue ); if( ( ulRegValue & phyBMSR_AN_COMPLETE ) != 0 ) { ulDoneMask |= ulBitMask; } } } } if( ulPhyMask == ulDoneMask ) { break; } if( xTaskCheckForTimeOut( &xTimer, &xRemainingTime ) != pdFALSE ) { FreeRTOS_printf( ( "xPhyReset: phyBMCR_RESET timed out ( done 0x%02lX )\n", ulDoneMask ) ); eventLogAdd( "ANtimed out"); break; } } eventLogAdd( "AN done %02lX / %02lX", ulDoneMask, ulPhyMask ); if( ulDoneMask != ( uint32_t)0u ) { ulBitMask = ( uint32_t )1u; pxPhyObject->ulLinkStatusMask &= ~( ulDoneMask ); for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++, ulBitMask <<= 1 ) { BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ]; uint32_t ulPhyID = pxPhyObject->ulPhyIDs[ xPhyIndex ]; if( ( ulDoneMask & ulBitMask ) == ( uint32_t )0u ) { continue; } /* Clear the 'phyBMCR_AN_RESTART' bit. */ pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_00_BMCR, pxPhyObject->ulBCRValue ); pxPhyObject->fnPhyRead( xPhyAddress, phyREG_01_BMSR, &ulRegValue); if( ( ulRegValue & phyBMSR_LINK_STATUS ) != 0 ) { ulPHYLinkStatus |= phyBMSR_LINK_STATUS; pxPhyObject->ulLinkStatusMask |= ulBitMask; } else { ulPHYLinkStatus &= ~( phyBMSR_LINK_STATUS ); } if( xHas_1F_PHYSPCS( ulPhyID ) ) { /* 31 RW PHY Special Control Status */ uint32_t ulControlStatus; pxPhyObject->fnPhyRead( xPhyAddress, phyREG_1F_PHYSPCS, &ulControlStatus); ulRegValue = 0; if( ( ulControlStatus & phyPHYSPCS_FULL_DUPLEX ) != 0 ) { ulRegValue |= phyPHYSTS_DUPLEX_STATUS; } if( ( ulControlStatus & phyPHYSPCS_SPEED_MASK ) == phyPHYSPCS_SPEED_10 ) { ulRegValue |= phyPHYSTS_SPEED_STATUS; } } else { /* Read the result of the auto-negotiation. */ pxPhyObject->fnPhyRead( xPhyAddress, PHYREG_10_PHYSTS, &ulRegValue); } FreeRTOS_printf( ( ">> Autonego ready: %08lx: %s duplex %u mbit %s status\n", ulRegValue, ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) ? "full" : "half", ( ulRegValue & phyPHYSTS_SPEED_STATUS ) ? 10 : 100, ( ( ulPHYLinkStatus |= phyBMSR_LINK_STATUS ) != 0) ? "high" : "low" ) ); eventLogAdd( "%s duplex %u mbit %s st", ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) ? "full" : "half", ( ulRegValue & phyPHYSTS_SPEED_STATUS ) ? 10 : 100, ( ( ulPHYLinkStatus |= phyBMSR_LINK_STATUS ) != 0) ? "high" : "low" ); { uint32_t regs[4]; int i,j; int address = 0x10; for (i = 0; i < 4; i++) { for (j = 0; j < 4; j++) { pxPhyObject->fnPhyRead( xPhyAddress, address, regs + j ); address++; } eventLogAdd("%04lX %04lX %04lX %04lX", regs[0], regs[1], regs[2], regs[3]); } } if( ( ulRegValue & phyPHYSTS_DUPLEX_STATUS ) != ( uint32_t )0u ) { pxPhyObject->xPhyProperties.ucDuplex = PHY_DUPLEX_FULL; } else { pxPhyObject->xPhyProperties.ucDuplex = PHY_DUPLEX_HALF; } if( ( ulRegValue & phyPHYSTS_SPEED_STATUS ) != 0 ) { pxPhyObject->xPhyProperties.ucSpeed = PHY_SPEED_10; } else { pxPhyObject->xPhyProperties.ucSpeed = PHY_SPEED_100; } } } /* if( ulDoneMask != ( uint32_t)0u ) */ return 0; }
BaseType_t xPhyConfigure( EthernetPhy_t *pxPhyObject, const PhyProperties_t *pxPhyProperties ) { uint32_t ulConfig, ulAdvertise; BaseType_t xPhyIndex; if( pxPhyObject->xPortCount < 1 ) { FreeRTOS_printf( ( "xPhyResetAll: No PHY's detected.\n" ) ); return -1; } /* The expected ID for the 'LAN8742A' is 0x0007c130. */ /* The expected ID for the 'LAN8720' is 0x0007c0f0. */ /* The expected ID for the 'DP83848I' is 0x20005C90. */ /* Set advertise register. */ if( ( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_AUTO ) && ( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_AUTO ) ) { ulAdvertise = phyADVERTISE_CSMA | phyADVERTISE_ALL; /* Reset auto-negotiation capability. */ } else { ulAdvertise = phyADVERTISE_CSMA; if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_AUTO ) { if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_FULL ) { ulAdvertise |= phyADVERTISE_10FULL | phyADVERTISE_100FULL; } else { ulAdvertise |= phyADVERTISE_10HALF | phyADVERTISE_100HALF; } } else if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_AUTO ) { if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_10 ) { ulAdvertise |= phyADVERTISE_10FULL | phyADVERTISE_10HALF; } else { ulAdvertise |= phyADVERTISE_100FULL | phyADVERTISE_100HALF; } } else if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_100 ) { if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_FULL ) { ulAdvertise |= phyADVERTISE_100FULL; } else { ulAdvertise |= phyADVERTISE_100HALF; } } else { if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_FULL ) { ulAdvertise |= phyADVERTISE_10FULL; } else { ulAdvertise |= phyADVERTISE_10HALF; } } } /* Send a reset commando to a set of PHY-ports. */ xPhyReset( pxPhyObject, xPhyGetMask( pxPhyObject ) ); for( xPhyIndex = 0; xPhyIndex < pxPhyObject->xPortCount; xPhyIndex++ ) { BaseType_t xPhyAddress = pxPhyObject->ucPhyIndexes[ xPhyIndex ]; uint32_t ulPhyID = pxPhyObject->ulPhyIDs[ xPhyIndex ]; /* Write advertise register. */ pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_04_ADVERTISE, ulAdvertise ); /* AN_EN AN1 AN0 Forced Mode 0 0 0 10BASE-T, Half-Duplex 0 0 1 10BASE-T, Full-Duplex 0 1 0 100BASE-TX, Half-Duplex 0 1 1 100BASE-TX, Full-Duplex AN_EN AN1 AN0 Advertised Mode 1 0 0 10BASE-T, Half/Full-Duplex 1 0 1 100BASE-TX, Half/Full-Duplex 1 1 0 10BASE-T Half-Duplex 100BASE-TX, Half-Duplex 1 1 1 10BASE-T, Half/Full-Duplex 100BASE-TX, Half/Full-Duplex */ /* Read Control register. */ pxPhyObject->fnPhyRead( xPhyAddress, phyREG_00_BMCR, &ulConfig ); ulConfig &= ~( phyBMCR_SPEED_100 | phyBMCR_FULL_DUPLEX ); ulConfig |= phyBMCR_AN_ENABLE; if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_100 ) { ulConfig |= phyBMCR_SPEED_100; } else if( pxPhyProperties->ucSpeed == ( uint8_t )PHY_SPEED_10 ) { ulConfig &= ~phyBMCR_SPEED_100; } if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_FULL ) { ulConfig |= phyBMCR_FULL_DUPLEX; } else if( pxPhyProperties->ucDuplex == ( uint8_t )PHY_DUPLEX_HALF ) { ulConfig &= ~phyBMCR_FULL_DUPLEX; } if( xHas_19_PHYCR( ulPhyID ) ) { uint32_t ulPhyControl; /* Read PHY Control register. */ pxPhyObject->fnPhyRead( xPhyAddress, phyREG_19_PHYCR, &ulPhyControl ); /* Clear bits which might get set: */ ulPhyControl &= ~( PHYCR_MDIX_EN|PHYCR_MDIX_FORCE ); if( pxPhyProperties->ucMDI_X == PHY_MDIX_AUTO ) { ulPhyControl |= PHYCR_MDIX_EN; } else if( pxPhyProperties->ucMDI_X == PHY_MDIX_CROSSED ) { /* Force direct link = Use crossed RJ45 cable. */ ulPhyControl &= ~PHYCR_MDIX_FORCE; } else { /* Force crossed link = Use direct RJ45 cable. */ ulPhyControl |= PHYCR_MDIX_FORCE; } /* update PHY Control Register. */ pxPhyObject->fnPhyWrite( xPhyAddress, phyREG_19_PHYCR, ulPhyControl ); } FreeRTOS_printf( ( "+TCP: advertise: %04lX config %04lX\n", ulAdvertise, ulConfig ) ); eventLogAdd( "adv: %04lX config %04lX", ulAdvertise, ulConfig ); } /* Keep these values for later use. */ pxPhyObject->ulBCRValue = ulConfig; pxPhyObject->ulACRValue = ulAdvertise; return 0; }
void emacps_set_rx_buffers( xemacpsif_s *xemacpsif, u32 ulCount ) { NetworkBufferDescriptor_t *pxBuffer; unsigned int FreeBds; int tail = xemacpsif->rxTail; int head = xemacpsif->rxHead; if( ulCount != 0 ) { FreeBds = ulCount; } else { FreeBds = is_rx_packets_available( NULL ); } while( FreeBds-- != 0 ) { pxBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, ( TickType_t ) 0 ); if( pxBuffer == NULL ) { FreeRTOS_printf( ("unable to alloc pbuf in recv_handler\n" ) ); dsb(); return; } dsb(); if( ( xemacpsif->rxSegments[ tail ].address & XEMACPS_RXBUF_NEW_MASK ) == 0 ) { FreeRTOS_printf( ("Buffer %d too far?\n", tail ) ); } if( pxDMA_rx_buffers[ tail ] != NULL ) { FreeRTOS_printf( ("Buffer %d not used?\n", tail ) ); } pxDMA_rx_buffers[ tail ] = ( void * )pxBuffer; if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 ) { Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE ); } { uint32_t addr = ( ( uint32_t )pxBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK; if( tail == ( ipconfigNIC_N_RX_DESC - 1 ) ) { addr |= XEMACPS_RXBUF_WRAP_MASK; } /* Clearing 'XEMACPS_RXBUF_NEW_MASK' 0x00000001 *< Used bit.. */ xemacpsif->rxSegments[ tail ].address = addr; xemacpsif->rxSegments[ tail ].flags = 0; } if( ++tail == ipconfigNIC_N_RX_DESC ) { tail = 0; } if( tail == head ) { break; } } xemacpsif->rxTail = tail; }
static uint32_t prvEMACRxPoll( void ) { unsigned char *pucUseBuffer; uint32_t ulReceiveCount, ulResult, ulReturnValue = 0; static NetworkBufferDescriptor_t *pxNextNetworkBufferDescriptor = NULL; const UBaseType_t xMinDescriptorsToLeave = 2UL; const TickType_t xBlockTime = pdMS_TO_TICKS( 100UL ); static IPStackEvent_t xRxEvent = { eNetworkRxEvent, NULL }; for( ;; ) { /* If pxNextNetworkBufferDescriptor was not left pointing at a valid descriptor then allocate one now. */ if( ( pxNextNetworkBufferDescriptor == NULL ) && ( uxGetNumberOfFreeNetworkBuffers() > xMinDescriptorsToLeave ) ) { pxNextNetworkBufferDescriptor = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, xBlockTime ); } if( pxNextNetworkBufferDescriptor != NULL ) { /* Point pucUseBuffer to the buffer pointed to by the descriptor. */ pucUseBuffer = ( unsigned char* ) ( pxNextNetworkBufferDescriptor->pucEthernetBuffer - ipconfigPACKET_FILLER_SIZE ); } else { /* As long as pxNextNetworkBufferDescriptor is NULL, the incoming messages will be flushed and ignored. */ pucUseBuffer = NULL; } /* Read the next packet from the hardware into pucUseBuffer. */ ulResult = gmac_dev_read( &gs_gmac_dev, pucUseBuffer, ipTOTAL_ETHERNET_FRAME_SIZE, &ulReceiveCount ); if( ( ulResult != GMAC_OK ) || ( ulReceiveCount == 0 ) ) { /* No data from the hardware. */ break; } if( pxNextNetworkBufferDescriptor == NULL ) { /* Data was read from the hardware, but no descriptor was available for it, so it will be dropped. */ iptraceETHERNET_RX_EVENT_LOST(); continue; } iptraceNETWORK_INTERFACE_RECEIVE(); pxNextNetworkBufferDescriptor->xDataLength = ( size_t ) ulReceiveCount; xRxEvent.pvData = ( void * ) pxNextNetworkBufferDescriptor; /* Send the descriptor to the IP task for processing. */ if( xSendEventStructToIPTask( &xRxEvent, xBlockTime ) != pdTRUE ) { /* The buffer could not be sent to the stack so must be released again. */ vReleaseNetworkBufferAndDescriptor( pxNextNetworkBufferDescriptor ); iptraceETHERNET_RX_EVENT_LOST(); FreeRTOS_printf( ( "prvEMACRxPoll: Can not queue return packet!\n" ) ); } /* Now the buffer has either been passed to the IP-task, or it has been released in the code above. */ pxNextNetworkBufferDescriptor = NULL; ulReturnValue++; } return ulReturnValue; }
static void prvEMACHandlerTask( void *pvParameters ) { TimeOut_t xPhyTime; TickType_t xPhyRemTime; UBaseType_t uxCount; #if( ipconfigZERO_COPY_TX_DRIVER != 0 ) NetworkBufferDescriptor_t *pxBuffer; #endif uint8_t *pucBuffer; BaseType_t xResult = 0; uint32_t xStatus; const TickType_t ulMaxBlockTime = pdMS_TO_TICKS( EMAC_MAX_BLOCK_TIME_MS ); /* Remove compiler warnings about unused parameters. */ ( void ) pvParameters; configASSERT( xEMACTaskHandle ); vTaskSetTimeOutState( &xPhyTime ); xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS ); for( ;; ) { vCheckBuffersAndQueue(); if( ( ulISREvents & EMAC_IF_ALL_EVENT ) == 0 ) { /* No events to process now, wait for the next. */ ulTaskNotifyTake( pdFALSE, ulMaxBlockTime ); } if( ( ulISREvents & EMAC_IF_RX_EVENT ) != 0 ) { ulISREvents &= ~EMAC_IF_RX_EVENT; /* Wait for the EMAC interrupt to indicate that another packet has been received. */ xResult = prvEMACRxPoll(); } if( ( ulISREvents & EMAC_IF_TX_EVENT ) != 0 ) { /* Future extension: code to release TX buffers if zero-copy is used. */ ulISREvents &= ~EMAC_IF_TX_EVENT; while( xQueueReceive( xTxBufferQueue, &pucBuffer, 0 ) != pdFALSE ) { #if( ipconfigZERO_COPY_TX_DRIVER != 0 ) { pxBuffer = pxPacketBuffer_to_NetworkBuffer( pucBuffer ); if( pxBuffer != NULL ) { vReleaseNetworkBufferAndDescriptor( pxBuffer ); tx_release_count[ 0 ]++; } else { tx_release_count[ 1 ]++; } } #else { tx_release_count[ 0 ]++; } #endif uxCount = uxQueueMessagesWaiting( ( QueueHandle_t ) xTXDescriptorSemaphore ); if( uxCount < GMAC_TX_BUFFERS ) { /* Tell the counting semaphore that one more TX descriptor is available. */ xSemaphoreGive( xTXDescriptorSemaphore ); } } } if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 ) { /* Future extension: logging about errors that occurred. */ ulISREvents &= ~EMAC_IF_ERR_EVENT; } if( xResult > 0 ) { /* A packet was received. No need to check for the PHY status now, but set a timer to check it later on. */ vTaskSetTimeOutState( &xPhyTime ); xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS ); xResult = 0; } else if( xTaskCheckForTimeOut( &xPhyTime, &xPhyRemTime ) != pdFALSE ) { /* Check the link status again. */ xStatus = ulReadMDIO( PHY_REG_01_BMSR ); if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != ( xStatus & BMSR_LINK_STATUS ) ) { ulPHYLinkStatus = xStatus; FreeRTOS_printf( ( "prvEMACHandlerTask: PHY LS now %d\n", ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) ); } vTaskSetTimeOutState( &xPhyTime ); if( ( ulPHYLinkStatus & BMSR_LINK_STATUS ) != 0 ) { xPhyRemTime = pdMS_TO_TICKS( PHY_LS_HIGH_CHECK_TIME_MS ); } else { xPhyRemTime = pdMS_TO_TICKS( PHY_LS_LOW_CHECK_TIME_MS ); } } } }
static void emacps_handle_error(void *arg, u8 Direction, u32 ErrorWord) { xemacpsif_s *xemacpsif; struct xtopology_t *xtopologyp; XEmacPs *xemacps; xemacpsif = (xemacpsif_s *)(arg); xtopologyp = &xXTopology; xemacps = &xemacpsif->emacps; /* Do not appear to be used. */ ( void ) xemacps; ( void ) xtopologyp; last_err_msg = NULL; if( ErrorWord != 0 ) { switch (Direction) { case XEMACPS_RECV: if( ( ErrorWord & XEMACPS_RXSR_HRESPNOK_MASK ) != 0 ) { last_err_msg = "Receive DMA error"; xNetworkInterfaceInitialise( ); } if( ( ErrorWord & XEMACPS_RXSR_RXOVR_MASK ) != 0 ) { last_err_msg = "Receive over run"; emacps_recv_handler(arg); emacps_set_rx_buffers( xemacpsif, 0 ); } if( ( ErrorWord & XEMACPS_RXSR_BUFFNA_MASK ) != 0 ) { last_err_msg = "Receive buffer not available"; emacps_recv_handler(arg); emacps_set_rx_buffers( xemacpsif, 0 ); } break; case XEMACPS_SEND: if( ( ErrorWord & XEMACPS_TXSR_HRESPNOK_MASK ) != 0 ) { last_err_msg = "Transmit DMA error"; xNetworkInterfaceInitialise( ); } if( ( ErrorWord & XEMACPS_TXSR_URUN_MASK ) != 0 ) { last_err_msg = "Transmit under run"; HandleTxErrors( xemacpsif ); } if( ( ErrorWord & XEMACPS_TXSR_BUFEXH_MASK ) != 0 ) { last_err_msg = "Transmit buffer exhausted"; HandleTxErrors( xemacpsif ); } if( ( ErrorWord & XEMACPS_TXSR_RXOVR_MASK ) != 0 ) { last_err_msg = "Transmit retry excessed limits"; HandleTxErrors( xemacpsif ); } if( ( ErrorWord & XEMACPS_TXSR_FRAMERX_MASK ) != 0 ) { last_err_msg = "Transmit collision"; emacps_check_tx( xemacpsif ); } break; } } // Break on this statement and inspect error_msg if you like if( last_err_msg != NULL ) { error_msg_count++; FreeRTOS_printf( ( "emacps_handle_error: %s\n", last_err_msg ) ); } }
XStatus init_dma(xemacpsif_s *xemacpsif) { NetworkBufferDescriptor_t *pxBuffer; int iIndex; UBaseType_t xRxSize; UBaseType_t xTxSize; struct xtopology_t *xtopologyp = &xXTopology; xRxSize = ipconfigNIC_N_RX_DESC * sizeof( xemacpsif->rxSegments[ 0 ] ); xTxSize = ipconfigNIC_N_TX_DESC * sizeof( xemacpsif->txSegments[ 0 ] ); /* Also round-up to 4KB */ xemacpsif->uTxUnitSize = ( ipTOTAL_ETHERNET_FRAME_SIZE + 0x1000ul ) & ~0xffful; /* * We allocate 65536 bytes for RX BDs which can accommodate a * maximum of 8192 BDs which is much more than any application * will ever need. */ xemacpsif->rxSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xRxSize ) ); xemacpsif->txSegments = ( struct xBD_TYPE * )( pucGetUncachedMemory ( xTxSize ) ); xemacpsif->tx_space = ( unsigned char * )( pucGetUncachedMemory ( ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize ) ); /* These variables will be used in XEmacPs_Start (see src/xemacps.c). */ xemacpsif->emacps.RxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->rxSegments; xemacpsif->emacps.TxBdRing.BaseBdAddr = ( uint32_t ) xemacpsif->txSegments; /* * Allocate RX descriptors, 1 RxBD at a time. */ for( iIndex = 0; iIndex < ipconfigNIC_N_RX_DESC; iIndex++ ) { pxBuffer = pxDMA_rx_buffers[ iIndex ]; if( pxBuffer == NULL ) { pxBuffer = pxGetNetworkBufferWithDescriptor( ipTOTAL_ETHERNET_FRAME_SIZE, ( TickType_t ) 0 ); if( pxBuffer == NULL ) { FreeRTOS_printf( ("Unable to allocate a network buffer in recv_handler\n" ) ); return -1; } } xemacpsif->rxSegments[ iIndex ].flags = 0; xemacpsif->rxSegments[ iIndex ].address = ( ( uint32_t )pxBuffer->pucEthernetBuffer ) & XEMACPS_RXBUF_ADD_MASK; pxDMA_rx_buffers[ iIndex ] = pxBuffer; /* Make sure this memory is not in cache for now. */ if( ucIsCachedMemory( pxBuffer->pucEthernetBuffer ) != 0 ) { Xil_DCacheInvalidateRange( ( ( uint32_t )pxBuffer->pucEthernetBuffer ) - ipconfigPACKET_FILLER_SIZE, (unsigned)ipTOTAL_ETHERNET_FRAME_SIZE ); } } xemacpsif->rxSegments[ ipconfigNIC_N_RX_DESC - 1 ].address |= XEMACPS_RXBUF_WRAP_MASK; memset( xemacpsif->tx_space, '\0', ipconfigNIC_N_TX_DESC * xemacpsif->uTxUnitSize ); clean_dma_txdescs( xemacpsif ); { uint32_t value; value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET ); // 1xxxx: Attempt to use INCR16 AHB bursts value = ( value & ~( XEMACPS_DMACR_BLENGTH_MASK ) ) | XEMACPS_DMACR_INCR16_AHB_BURST; #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 ) value |= XEMACPS_DMACR_TCPCKSUM_MASK; #else #warning Are you sure the EMAC should not calculate outgoing checksums? value &= ~XEMACPS_DMACR_TCPCKSUM_MASK; #endif XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_DMACR_OFFSET, value ); } { uint32_t value; value = XEmacPs_ReadReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET ); /* Network buffers are 32-bit aligned + 2 bytes (because ipconfigPACKET_FILLER_SIZE = 2 ). Now tell the EMAC that received messages should be stored at "address + 2". */ value = ( value & ~XEMACPS_NWCFG_RXOFFS_MASK ) | 0x8000; #if( ipconfigDRIVER_INCLUDED_RX_IP_CHECKSUM != 0 ) value |= XEMACPS_NWCFG_RXCHKSUMEN_MASK; #else #warning Are you sure the EMAC should not calculate incoming checksums? value &= ~XEMACPS_NWCFG_RXCHKSUMEN_MASK; #endif XEmacPs_WriteReg( xemacpsif->emacps.Config.BaseAddress, XEMACPS_NWCFG_OFFSET, value ); } /* * Connect the device driver handler that will be called when an * interrupt for the device occurs, the handler defined above performs * the specific interrupt processing for the device. */ XScuGic_RegisterHandler(INTC_BASE_ADDR, xtopologyp->scugic_emac_intr, (Xil_ExceptionHandler)XEmacPs_IntrHandler, (void *)&xemacpsif->emacps); /* * Enable the interrupt for emacps. */ EmacEnableIntr( ); return 0; }
static void prvNTPTask( void *pvParameters ) { BaseType_t xServerIndex = 3; struct freertos_sockaddr xAddress; #if( ipconfigUSE_CALLBACKS != 0 ) F_TCP_UDP_Handler_t xHandler; #endif /* ipconfigUSE_CALLBACKS != 0 */ xStatus = EStatusLookup; #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) || ( ipconfigUSE_CALLBACKS != 0 ) { xNTPWakeupSem = xSemaphoreCreateBinary(); } #endif #if( ipconfigUSE_CALLBACKS != 0 ) { memset( &xHandler, '\0', sizeof ( xHandler ) ); xHandler.pOnUdpReceive = xOnUdpReceive; FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_UDP_RECV_HANDLER, ( void * ) &xHandler, sizeof( xHandler ) ); } #endif #if( ipconfigSOCKET_HAS_USER_SEMAPHORE != 0 ) { FreeRTOS_setsockopt( xUDPSocket, 0, FREERTOS_SO_SET_SEMAPHORE, ( void * ) &xNTPWakeupSem, sizeof( xNTPWakeupSem ) ); } #endif for( ; ; ) { switch( xStatus ) { case EStatusLookup: if( ( ulIPAddressFound == 0ul ) || ( ulIPAddressFound == ~0ul ) ) { if( ++xServerIndex == sizeof pcTimeServers / sizeof pcTimeServers[ 0 ] ) { xServerIndex = 0; } FreeRTOS_printf( ( "Looking up server '%s'\n", pcTimeServers[ xServerIndex ] ) ); FreeRTOS_gethostbyname_a( pcTimeServers[ xServerIndex ], vDNS_callback, (void *)NULL, 1200 ); } else { xStatus = EStatusAsking; } break; case EStatusAsking: { char pcBuf[16]; prvNTPPacketInit( ); xAddress.sin_addr = ulIPAddressFound; xAddress.sin_port = FreeRTOS_htons( NTP_PORT ); FreeRTOS_inet_ntoa( xAddress.sin_addr, pcBuf ); FreeRTOS_printf( ( "Sending UDP message to %s:%u\n", pcBuf, FreeRTOS_ntohs( xAddress.sin_port ) ) ); uxSendTime = xTaskGetTickCount( ); FreeRTOS_sendto( xUDPSocket, ( void * )&xNTPPacket, sizeof( xNTPPacket ), 0, &xAddress, sizeof( xAddress ) ); } break; case EStatusPause: break; case EStatusFailed: break; } #if( ipconfigUSE_CALLBACKS != 0 ) { xSemaphoreTake( xNTPWakeupSem, 5000 ); } #else { uint32_t xAddressSize; BaseType_t xReturned; xAddressSize = sizeof( xAddress ); xReturned = FreeRTOS_recvfrom( xUDPSocket, ( void * ) cRecvBuffer, sizeof( cRecvBuffer ), 0, &xAddress, &xAddressSize ); switch( xReturned ) { case 0: case -pdFREERTOS_ERRNO_EAGAIN: case -pdFREERTOS_ERRNO_EINTR: break; default: if( xReturned < sizeof( xNTPPacket ) ) { FreeRTOS_printf( ( "FreeRTOS_recvfrom: returns %ld\n", xReturned ) ); } else { prvReadTime( ( struct SNtpPacket *)cRecvBuffer ); if( xStatus != EStatusPause ) { xStatus = EStatusPause; } } break; } } #endif } }
static void prvReadTime( struct SNtpPacket * pxPacket ) { FF_TimeStruct_t xTimeStruct; time_t uxPreviousSeconds; time_t uxPreviousMS; time_t uxCurrentSeconds; time_t uxCurrentMS; const char *pcTimeUnit; int32_t ilDiff; TickType_t uxTravelTime; uxTravelTime = xTaskGetTickCount() - uxSendTime; /* Transform the contents of the fields from big to native endian. */ prvSwapFields( pxPacket ); uxCurrentSeconds = pxPacket->receiveTimestamp.seconds - TIME1970; uxCurrentMS = pxPacket->receiveTimestamp.fraction / 4294967; uxCurrentSeconds += uxCurrentMS / 1000; uxCurrentMS = uxCurrentMS % 1000; // Get the last time recorded uxPreviousSeconds = FreeRTOS_get_secs_msec( &uxPreviousMS ); // Set the new time with precision in msec. */ FreeRTOS_set_secs_msec( &uxCurrentSeconds, &uxCurrentMS ); if( uxCurrentSeconds >= uxPreviousSeconds ) { ilDiff = ( int32_t ) ( uxCurrentSeconds - uxPreviousSeconds ); } else { ilDiff = 0 - ( int32_t ) ( uxPreviousSeconds - uxCurrentSeconds ); } if( ( ilDiff < -5 ) || ( ilDiff > 5 ) ) { /* More than 5 seconds difference. */ pcTimeUnit = "sec"; } else { /* Less than or equal to 5 second difference. */ uint32_t ulLowest = ( uxCurrentSeconds <= uxPreviousSeconds ) ? uxCurrentSeconds : uxPreviousSeconds; int32_t iCurMS = 1000 * ( uxCurrentSeconds - ulLowest ) + uxCurrentMS; int32_t iPrevMS = 1000 * ( uxPreviousSeconds - ulLowest ) + uxPreviousMS; ilDiff = iCurMS - iPrevMS; pcTimeUnit = "ms"; } uxCurrentSeconds -= iTimeZone; FreeRTOS_gmtime_r( &uxCurrentSeconds, &xTimeStruct ); /* 378.067 [NTP client] NTP time: 9/11/2015 16:11:19.559 Diff -20 ms (289 ms) 379.441 [NTP client] NTP time: 9/11/2015 16:11:20.933 Diff 0 ms (263 ms) */ FreeRTOS_printf( ("NTP time: %d/%d/%02d %2d:%02d:%02d.%03u Diff %d %s (%lu ms)\n", xTimeStruct.tm_mday, xTimeStruct.tm_mon + 1, xTimeStruct.tm_year + 1900, xTimeStruct.tm_hour, xTimeStruct.tm_min, xTimeStruct.tm_sec, ( unsigned )uxCurrentMS, ( unsigned )ilDiff, pcTimeUnit, uxTravelTime ) ); /* Remove compiler warnings in case FreeRTOS_printf() is not used. */ ( void ) pcTimeUnit; ( void ) uxTravelTime; }