*/\r
\r
/*\r
- * FreeRTOS+TCP V2.0.3\r
+ * FreeRTOS+TCP V2.0.11\r
* Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.\r
*\r
* Permission is hereby granted, free of charge, to any person obtaining a copy of\r
*\r
* http://aws.amazon.com/freertos\r
* http://www.FreeRTOS.org\r
- */\r
-\r
+*/\r
\r
/* Standard includes. */\r
#include <stdint.h>\r
#include "NetworkInterface.h"\r
#include "phyHandling.h"\r
\r
+#define __STM32_HAL_LEGACY 1\r
+\r
/* ST includes. */\r
-#ifdef STM32F7xx\r
+#if defined( STM32F7xx )\r
#include "stm32f7xx_hal.h"\r
-#else\r
+#elif defined( STM32F4xx )\r
#include "stm32f4xx_hal.h"\r
+#elif defined( STM32F2xx )\r
+ #include "stm32f2xx_hal.h"\r
+#else\r
+ #error What part?\r
#endif\r
\r
+#include "stm32fxx_hal_eth.h"\r
+\r
/* Interrupt events to process. Currently only the Rx event is processed\r
although code for other events is included to allow for possible future\r
expansion. */\r
ETH_DMA_IT_FBE | ETH_DMA_IT_RWT | ETH_DMA_IT_RPS | ETH_DMA_IT_RBU | ETH_DMA_IT_R | \\r
ETH_DMA_IT_TU | ETH_DMA_IT_RO | ETH_DMA_IT_TJT | ETH_DMA_IT_TPS | ETH_DMA_IT_T )\r
\r
-\r
+#ifndef niEMAC_HANDLER_TASK_PRIORITY\r
+ #define niEMAC_HANDLER_TASK_PRIORITY configMAX_PRIORITIES - 1\r
+#endif\r
\r
#define ipFRAGMENT_OFFSET_BIT_MASK ( ( uint16_t ) 0x0fff ) /* The bits in the two byte IP header field that make up the fragment offset value. */\r
\r
#endif /* STM32F7xx */\r
#endif /* ipconfigUSE_RMII */\r
\r
-\r
+#if( ipconfigUSE_RMII != 0 )\r
+ #warning Using RMII, make sure if this is correct\r
+#else\r
+ #warning Using MII, make sure if this is correct\r
+#endif\r
\r
/*-----------------------------------------------------------*/\r
\r
*/\r
static void prvDMARxDescListInit( void );\r
\r
-/* After packets have been sent, the network\r
-buffers will be released. */\r
-static void vClearTXBuffers( void );\r
+ /* After packets have been sent, the network\r
+ buffers will be released. */\r
+ static void vClearTXBuffers( void );\r
\r
/*-----------------------------------------------------------*/\r
\r
/* Ethernet handle. */\r
static ETH_HandleTypeDef xETH;\r
\r
-/* xTXDescriptorSemaphore is a counting semaphore with\r
-a maximum count of ETH_TXBUFNB, which is the number of\r
-DMA TX descriptors. */\r
-static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
+ /* xTXDescriptorSemaphore is a counting semaphore with\r
+ a maximum count of ETH_TXBUFNB, which is the number of\r
+ DMA TX descriptors. */\r
+ static SemaphoreHandle_t xTXDescriptorSemaphore = NULL;\r
\r
/*\r
* Note: it is adviced to define both\r
static __IO ETH_DMADescTypeDef *DMATxDescToClear;\r
#endif\r
\r
-/* ucMACAddress as it appears in main.c */\r
-extern const uint8_t ucMACAddress[ 6 ];\r
-\r
/* Holds the handle of the task used as a deferred interrupt processor. The\r
handle is used so direct notifications can be sent to the task for all EMAC/DMA\r
related interrupts. */\r
}\r
/*-----------------------------------------------------------*/\r
\r
-void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )\r
-{\r
-BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
-\r
- /* This call-back is only useful in case packets are being sent\r
- zero-copy. Once they're sent, the buffers will be released\r
- by the function vClearTXBuffers(). */\r
- ulISREvents |= EMAC_IF_TX_EVENT;\r
- /* Wakeup the prvEMACHandlerTask. */\r
- if( xEMACTaskHandle != NULL )\r
+ void HAL_ETH_TxCpltCallback( ETH_HandleTypeDef *heth )\r
{\r
- vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
- portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
- }\r
+ BaseType_t xHigherPriorityTaskWoken = pdFALSE;\r
+\r
+ /* This call-back is only useful in case packets are being sent\r
+ zero-copy. Once they're sent, the buffers will be released\r
+ by the function vClearTXBuffers(). */\r
+ ulISREvents |= EMAC_IF_TX_EVENT;\r
+ /* Wakeup the prvEMACHandlerTask. */\r
+ if( xEMACTaskHandle != NULL )\r
+ {\r
+ vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );\r
+ portYIELD_FROM_ISR( xHigherPriorityTaskWoken );\r
+ }\r
\r
-}\r
+ }\r
/*-----------------------------------------------------------*/\r
\r
-static void vClearTXBuffers()\r
-{\r
-__IO ETH_DMADescTypeDef *txLastDescriptor = xETH.TxDesc;\r
+ static void vClearTXBuffers()\r
+ {\r
+ __IO ETH_DMADescTypeDef *txLastDescriptor = xETH.TxDesc;\r
size_t uxCount = ( ( UBaseType_t ) ETH_TXBUFNB ) - uxSemaphoreGetCount( xTXDescriptorSemaphore );\r
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
NetworkBufferDescriptor_t *pxNetworkBuffer;\r
uint8_t *ucPayLoad;\r
#endif\r
\r
- /* This function is called after a TX-completion interrupt.\r
- It will release each Network Buffer used in xNetworkInterfaceOutput().\r
- 'uxCount' represents the number of descriptors given to DMA for transmission.\r
- After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */\r
- while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )\r
- {\r
- if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )\r
+ /* This function is called after a TX-completion interrupt.\r
+ It will release each Network Buffer used in xNetworkInterfaceOutput().\r
+ 'uxCount' represents the number of descriptors given to DMA for transmission.\r
+ After sending a packet, the DMA will clear the 'ETH_DMATXDESC_OWN' bit. */\r
+ while( ( uxCount > 0 ) && ( ( DMATxDescToClear->Status & ETH_DMATXDESC_OWN ) == 0 ) )\r
{\r
- break;\r
- }\r
+ if( ( DMATxDescToClear == txLastDescriptor ) && ( uxCount != ETH_TXBUFNB ) )\r
+ {\r
+ break;\r
+ }\r
#if( ipconfigZERO_COPY_TX_DRIVER != 0 )\r
{\r
ucPayLoad = ( uint8_t * )DMATxDescToClear->Buffer1Addr;\r
}\r
#endif /* ipconfigZERO_COPY_TX_DRIVER */\r
\r
- DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );\r
+ DMATxDescToClear = ( ETH_DMADescTypeDef * )( DMATxDescToClear->Buffer2NextDescAddr );\r
\r
- uxCount--;\r
- /* Tell the counting semaphore that one more TX descriptor is available. */\r
- xSemaphoreGive( xTXDescriptorSemaphore );\r
+ uxCount--;\r
+ /* Tell the counting semaphore that one more TX descriptor is available. */\r
+ xSemaphoreGive( xTXDescriptorSemaphore );\r
+ }\r
}\r
-}\r
/*-----------------------------------------------------------*/\r
\r
BaseType_t xNetworkInterfaceInitialise( void )\r
\r
if( xEMACTaskHandle == NULL )\r
{\r
- if( xTXDescriptorSemaphore == NULL )\r
- {\r
- xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );\r
- configASSERT( xTXDescriptorSemaphore );\r
- }\r
+ if( xTXDescriptorSemaphore == NULL )\r
+ {\r
+ xTXDescriptorSemaphore = xSemaphoreCreateCounting( ( UBaseType_t ) ETH_TXBUFNB, ( UBaseType_t ) ETH_TXBUFNB );\r
+ configASSERT( xTXDescriptorSemaphore );\r
+ }\r
\r
/* Initialise ETH */\r
\r
/* Value of PhyAddress doesn't matter, will be probed for. */\r
xETH.Init.PhyAddress = 0;\r
\r
- xETH.Init.MACAddr = ( uint8_t *) ucMACAddress;\r
+ xETH.Init.MACAddr = ( uint8_t *)FreeRTOS_GetMACAddress();\r
xETH.Init.RxMode = ETH_RXINTERRUPT_MODE;\r
\r
/* using the ETH_CHECKSUM_BY_HARDWARE option:\r
}\r
#else\r
{\r
- xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;\r
+ xETH.Init.MediaInterface = ETH_MEDIA_INTERFACE_MII;\r
}\r
#endif /* ipconfigUSE_RMII */\r
\r
memset( &DMATxDscrTab, '\0', sizeof( DMATxDscrTab ) );\r
memset( &DMARxDscrTab, '\0', sizeof( DMARxDscrTab ) );\r
\r
- /* Initialize Tx Descriptors list: Chain Mode */\r
- DMATxDescToClear = DMATxDscrTab;\r
+ /* Initialize Tx Descriptors list: Chain Mode */\r
+ DMATxDescToClear = DMATxDscrTab;\r
\r
/* Initialise TX-descriptors. */\r
prvDMATxDescListInit();\r
possible priority to ensure the interrupt handler can return directly\r
to it. The task's handle is stored in xEMACTaskHandle so interrupts can\r
notify the task when there is something to process. */\r
- xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, configMAX_PRIORITIES - 1, &xEMACTaskHandle );\r
+ xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL, niEMAC_HANDLER_TASK_PRIORITY, &xEMACTaskHandle );\r
} /* if( xEMACTaskHandle == NULL ) */\r
\r
if( xPhyObject.ulLinkStatusMask != 0 )\r
/* Do not wait too long for a free TX DMA buffer. */\r
const TickType_t xBlockTimeTicks = pdMS_TO_TICKS( 50u );\r
\r
- #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
+ /* Open a do {} while ( 0 ) loop to be able to call break. */\r
+ do\r
{\r
- ProtocolPacket_t *pxPacket;\r
-\r
- #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+ if( xCheckLoopback( pxDescriptor, bReleaseAfterSend ) != 0 )\r
{\r
- configASSERT( bReleaseAfterSend != 0 );\r
+ /* The packet has been sent back to the IP-task.\r
+ The IP-task will further handle it.\r
+ Do not release the descriptor. */\r
+ bReleaseAfterSend = pdFALSE;\r
+ break;\r
}\r
- #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
+ #if( ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM != 0 )\r
+ {\r
+ ProtocolPacket_t *pxPacket;\r
\r
- /* If the peripheral must calculate the checksum, it wants\r
- the protocol checksum to have a value of zero. */\r
- pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer );\r
+ #if( ipconfigZERO_COPY_RX_DRIVER != 0 )\r
+ {\r
+ configASSERT( bReleaseAfterSend != 0 );\r
+ }\r
+ #endif /* ipconfigZERO_COPY_RX_DRIVER */\r
\r
- if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP )\r
- {\r
- pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;\r
- }\r
- }\r
- #endif\r
+ /* If the peripheral must calculate the checksum, it wants\r
+ the protocol checksum to have a value of zero. */\r
+ pxPacket = ( ProtocolPacket_t * ) ( pxDescriptor->pucEthernetBuffer );\r
\r
- /* Open a do {} while ( 0 ) loop to be able to call break. */\r
- do\r
- {\r
+ if( pxPacket->xICMPPacket.xIPHeader.ucProtocol == ipPROTOCOL_ICMP )\r
+ {\r
+ pxPacket->xICMPPacket.xICMPHeader.usChecksum = ( uint16_t )0u;\r
+ }\r
+ }\r
+ #endif /* ipconfigDRIVER_INCLUDED_TX_IP_CHECKSUM */\r
if( xPhyObject.ulLinkStatusMask != 0 )\r
{\r
if( xSemaphoreTake( xTXDescriptorSemaphore, xBlockTimeTicks ) != pdPASS )\r
pxDmaTxDesc->Status |= ETH_DMATXDESC_FS | ETH_DMATXDESC_LS;\r
/* Set frame size */\r
pxDmaTxDesc->ControlBufferSize = ( ulTransmitSize & ETH_DMATXDESC_TBS1 );\r
+\r
+ #if( NETWORK_BUFFERS_CACHED != 0 )\r
+ {\r
+ BaseType_t xlength = CACHE_LINE_SIZE * ( ( ulTransmitSize + NETWORK_BUFFER_HEADER_SIZE + CACHE_LINE_SIZE - 1 ) / CACHE_LINE_SIZE );\r
+ uint32_t *pulBuffer = ( uint32_t )( pxDescriptor->pucEthernetBuffer - NETWORK_BUFFER_HEADER_SIZE );\r
+ cache_clean_invalidate_by_addr( pulBuffer, xlength );\r
+ }\r
+ #endif\r
+\r
/* Set Own bit of the Tx descriptor Status: gives the buffer back to ETHERNET DMA */\r
pxDmaTxDesc->Status |= ETH_DMATXDESC_OWN;\r
\r
}\r
\r
/* Obtain the size of the packet and put it into the "usReceivedLength" variable. */\r
- /* In order to make the code easier and faster, only packets in a single buffer\r
- will be accepted. This can be done by making the buffers large enough to\r
- hold a complete Ethernet packet (1536 bytes). */\r
- if( xReceivedLength > 0ul && xReceivedLength < ETH_RX_BUF_SIZE ) \r
+\r
+ /* get received frame */\r
+ if( xReceivedLength > 0ul )\r
{\r
+ /* In order to make the code easier and faster, only packets in a single buffer\r
+ will be accepted. This can be done by making the buffers large enough to\r
+ hold a complete Ethernet packet (1536 bytes).\r
+ Therefore, two sanity checks: */\r
+ configASSERT( xReceivedLength <= ETH_RX_BUF_SIZE );\r
+\r
if( ( pxDMARxDescriptor->Status & ( ETH_DMARXDESC_CE | ETH_DMARXDESC_IPV4HCE | ETH_DMARXDESC_FT ) ) != ETH_DMARXDESC_FT )\r
{\r
/* Not an Ethernet frame-type or a checmsum error. */\r
\r
\r
BaseType_t xSTM32_PhyRead( BaseType_t xAddress, BaseType_t xRegister, uint32_t *pulValue )\r
-{\r
+ {\r
uint16_t usPrevAddress = xETH.Init.PhyAddress;\r
BaseType_t xResult;\r
HAL_StatusTypeDef xHALResult;\r
xResult = -1;\r
}\r
return xResult;\r
-}\r
+ }\r
/*-----------------------------------------------------------*/\r
\r
BaseType_t xSTM32_PhyWrite( BaseType_t xAddress, BaseType_t xRegister, uint32_t ulValue )\r
-{\r
+ {\r
uint16_t usPrevAddress = xETH.Init.PhyAddress;\r
BaseType_t xResult;\r
HAL_StatusTypeDef xHALResult;\r
xETH.Init.PhyAddress = usPrevAddress;\r
\r
if( xHALResult == HAL_OK )\r
- {\r
+ {\r
xResult = 0;\r
- }\r
- else\r
- {\r
+ }\r
+ else\r
+ {\r
xResult = -1;\r
- }\r
+ }\r
return xResult;\r
-}\r
-/*-----------------------------------------------------------*/\r
-\r
-void phy_test()\r
-{\r
-BaseType_t xPhyCount;\r
-BaseType_t xPhyIndex;\r
-\r
- vPhyInitialise( &xPhyObject, xSTM32_PhyRead, xSTM32_PhyWrite );\r
- xPhyCount = xPhyDiscover( &xPhyObject );\r
- FreeRTOS_printf( ( "PHY count %ld\n", xPhyCount ) );\r
- for( xPhyIndex = 0; xPhyIndex < xPhyCount; xPhyIndex++ )\r
- {\r
- FreeRTOS_printf( ( "PHY[%d] at address %d ( 0x%08X )\n",\r
- xPhyIndex,\r
- xPhyObject.ucPhyIndexes[ xPhyIndex ],\r
- xPhyObject.ulPhyIDs[ xPhyIndex ] ) );\r
-\r
}\r
- \r
-}\r
+/*-----------------------------------------------------------*/\r
\r
void vMACBProbePhy( void )\r
{\r
{\r
xPhyStartAutoNegotiation( &xPhyObject, xPhyGetMask( &xPhyObject ) );\r
\r
- /* Configure the MAC with the Duplex Mode fixed by the\r
- auto-negotiation process. */\r
+ /* Configure the MAC with the Duplex Mode fixed by the\r
+ auto-negotiation process. */\r
if( xPhyObject.xPhyProperties.ucDuplex == PHY_DUPLEX_FULL )\r
- {\r
- xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
- }\r
- else\r
- {\r
- xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;\r
- }\r
+ {\r
+ xETH.Init.DuplexMode = ETH_MODE_FULLDUPLEX;\r
+ }\r
+ else\r
+ {\r
+ xETH.Init.DuplexMode = ETH_MODE_HALFDUPLEX;\r
+ }\r
\r
- /* Configure the MAC with the speed fixed by the\r
- auto-negotiation process. */\r
+ /* Configure the MAC with the speed fixed by the\r
+ auto-negotiation process. */\r
if( xPhyObject.xPhyProperties.ucSpeed == PHY_SPEED_10 )\r
- {\r
- xETH.Init.Speed = ETH_SPEED_10M;\r
- }\r
- else\r
- {\r
- xETH.Init.Speed = ETH_SPEED_100M;\r
- }\r
+ {\r
+ xETH.Init.Speed = ETH_SPEED_10M;\r
+ }\r
+ else\r
+ {\r
+ xETH.Init.Speed = ETH_SPEED_100M;\r
+ }\r
}\r
else /* AutoNegotiation Disable */\r
{\r
\r
/* Uncomment this in case BufferAllocation_1.c is used. */\r
\r
-/*\r
#define niBUFFER_1_PACKET_SIZE 1536\r
\r
-static __attribute__ ((section(".first_data"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );\r
-\r
void vNetworkInterfaceAllocateRAMToBuffers( NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )\r
{\r
-\r
+static __attribute__ ((section(".first_data"))) uint8_t ucNetworkPackets[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS * niBUFFER_1_PACKET_SIZE ] __attribute__ ( ( aligned( 32 ) ) );\r
uint8_t *ucRAMBuffer = ucNetworkPackets;\r
uint32_t ul;\r
\r
ucRAMBuffer += niBUFFER_1_PACKET_SIZE;\r
}\r
}\r
-*/\r
/*-----------------------------------------------------------*/\r
\r
static void prvEMACHandlerTask( void *pvParameters )\r
{\r
/* Code to release TX buffers if zero-copy is used. */\r
ulISREvents &= ~EMAC_IF_TX_EVENT;\r
- /* Check if DMA packets have been delivered. */\r
- vClearTXBuffers();\r
- }\r
+ /* Check if DMA packets have been delivered. */\r
+ vClearTXBuffers();\r
+ }\r
\r
if( ( ulISREvents & EMAC_IF_ERR_EVENT ) != 0 )\r
{\r
ulISREvents &= ~EMAC_IF_ERR_EVENT;\r
}\r
if( xPhyCheckLinkStatus( &xPhyObject, xResult ) != 0 )\r
- {\r
+ {\r
/* Something has changed to a Link Status, need re-check. */\r
- prvEthernetUpdateConfig( pdFALSE );\r
- }\r
+ prvEthernetUpdateConfig( pdFALSE );\r
+ }\r
}\r
}\r
/*-----------------------------------------------------------*/\r