You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
506 lines
18 KiB
Plaintext
506 lines
18 KiB
Plaintext
/*
|
|
FreeRTOS V5.4.2 - Copyright (C) 2009 Real Time Engineers Ltd.
|
|
|
|
This file is part of the FreeRTOS distribution.
|
|
|
|
FreeRTOS is free software; you can redistribute it and/or modify it under
|
|
the terms of the GNU General Public License (version 2) as published by the
|
|
Free Software Foundation and modified by the FreeRTOS exception.
|
|
**NOTE** The exception to the GPL is included to allow you to distribute a
|
|
combined work that includes FreeRTOS without being obliged to provide the
|
|
source code for proprietary components outside of the FreeRTOS kernel.
|
|
Alternative commercial license and support terms are also available upon
|
|
request. See the licensing section of http://www.FreeRTOS.org for full
|
|
license details.
|
|
|
|
FreeRTOS is distributed in the hope that it will be useful, but WITHOUT
|
|
ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
|
more details.
|
|
|
|
You should have received a copy of the GNU General Public License along
|
|
with FreeRTOS; if not, write to the Free Software Foundation, Inc., 59
|
|
Temple Place, Suite 330, Boston, MA 02111-1307 USA.
|
|
|
|
|
|
***************************************************************************
|
|
* *
|
|
* Looking for a quick start? Then check out the FreeRTOS eBook! *
|
|
* See http://www.FreeRTOS.org/Documentation for details *
|
|
* *
|
|
***************************************************************************
|
|
|
|
1 tab == 4 spaces!
|
|
|
|
Please ensure to read the configuration and relevant port sections of the
|
|
online documentation.
|
|
|
|
http://www.FreeRTOS.org - Documentation, latest information, license and
|
|
contact details.
|
|
|
|
http://www.SafeRTOS.com - A version that is certified for use in safety
|
|
critical systems.
|
|
|
|
http://www.OpenRTOS.com - Commercial support, development, porting,
|
|
licensing and training services.
|
|
*/
|
|
|
|
/* FreeRTOS includes. */
|
|
#include "FreeRTOS.h"
|
|
#include "semphr.h"
|
|
#include "task.h"
|
|
#include "emac.h"
|
|
|
|
/* Library includes. */
|
|
#include "stm32fxxx_eth.h"
|
|
#include "stm32f10x_gpio.h"
|
|
#include "stm32f10x_rcc.h"
|
|
#include "stm32f10x_nvic.h"
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* Hardware specifics. */
|
|
#define uipRCC_MAC_CLOCK ( 1UL << 14UL )
|
|
#define uipRCC_MAC_TX_CLOCK ( 1UL << 15UL )
|
|
#define uipRCC_MAC_RX_CLOCK ( 1UL << 16UL )
|
|
#define uipPHY_ADDRESS ( 1 )
|
|
#define uipENET_IRQ_NUM ( 61 )
|
|
#define uipMODE_MII ( 1UL << 23UL )
|
|
#define uipREMAP_MAC_IO ( 1UL << 21UL )
|
|
|
|
/* The number of descriptors to chain together for use by the Rx DMA. */
|
|
#define uipNUM_RX_DESCRIPTORS 4
|
|
|
|
/* The total number of buffers to be available. At most (?) there should be
|
|
one available for each Rx descriptor, one for current use, and one that is
|
|
in the process of being transmitted. */
|
|
#define uipNUM_BUFFERS ( uipNUM_RX_DESCRIPTORS + 2 )
|
|
|
|
/* Each buffer is sized to fit an entire Ethernet packet. This is for
|
|
simplicity and speed, but could waste RAM. */
|
|
#define uipMAX_PACKET_SIZE 1520
|
|
|
|
/* The field in the descriptor that is unused by this configuration is used to
|
|
hold the send count. This is just #defined to a meaningful name. */
|
|
#define SendCount Buffer2NextDescAddr
|
|
|
|
/* If no buffers are available, then wait this long before looking again.... */
|
|
#define uipBUFFER_WAIT_DELAY ( 3 / portTICK_RATE_MS )
|
|
|
|
/* ...and don't look more than this many times. */
|
|
#define uipBUFFER_WAIT_ATTEMPTS ( 30 )
|
|
|
|
/* Let the DMA know that a new descriptor has been made available to it. */
|
|
#define prvRxDescriptorAvailable() ETH_DMA->DMARPDR = 0
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/*
|
|
* Configure the IO for Ethernet use.
|
|
*/
|
|
static void prvSetupEthGPIO( void );
|
|
|
|
/*
|
|
* Return a pointer to an unused buffer, marking the returned buffer as now
|
|
* in use.
|
|
*/
|
|
static unsigned char *prvGetNextBuffer( void );
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
/* Allocate the Rx descriptors used by the DMA. */
|
|
static ETH_DMADESCTypeDef xRxDescriptors[ uipNUM_RX_DESCRIPTORS ] __attribute__((aligned(4)));
|
|
|
|
/* Allocate the descriptor used for transmitting. It might be that better
|
|
performance could be achieved by having more than one Tx descriptor, but
|
|
in this simple case only one is used. */
|
|
static volatile ETH_DMADESCTypeDef xTxDescriptor __attribute__((aligned(4)));
|
|
|
|
/* Buffers used for receiving and transmitting data. */
|
|
static unsigned char ucMACBuffers[ uipNUM_BUFFERS ][ uipMAX_PACKET_SIZE ] __attribute__((aligned(4)));
|
|
|
|
/* Each ucBufferInUse index corresponds to a position in the same index in the
|
|
ucMACBuffers array. If the index contains a 1 then the buffer within
|
|
ucMACBuffers is in use, if it contains a 0 then the buffer is free. */
|
|
static unsigned char ucBufferInUse[ uipNUM_BUFFERS ] = { 0 };
|
|
|
|
/* Index to the Rx descriptor to inspect next when looking for a received
|
|
packet. */
|
|
static unsigned long ulNextDescriptor;
|
|
|
|
/* The uip_buffer is not a fixed array, but instead gets pointed to the buffers
|
|
allocated within this file. */
|
|
extern unsigned char * uip_buf;
|
|
|
|
/*-----------------------------------------------------------*/
|
|
|
|
portBASE_TYPE xEthInitialise( void )
|
|
{
|
|
static ETH_InitTypeDef xEthInit; /* Static so as not to take up too much stack space. */
|
|
NVIC_InitTypeDef xNVICInit;
|
|
const unsigned char ucMACAddress[] = { configMAC_ADDR0, configMAC_ADDR1, configMAC_ADDR2, configMAC_ADDR3, configMAC_ADDR4, configMAC_ADDR5 };
|
|
portBASE_TYPE xReturn;
|
|
unsigned long ul;
|
|
|
|
/* Start with things in a safe known state. */
|
|
ETH_DeInit();
|
|
for( ul = 0; ul < uipNUM_RX_DESCRIPTORS; ul++ )
|
|
{
|
|
ETH_DMARxDescReceiveITConfig( &( xRxDescriptors[ ul ] ), DISABLE );
|
|
}
|
|
|
|
/* Route clock to the peripheral. */
|
|
RCC->AHBENR |= ( uipRCC_MAC_CLOCK | uipRCC_MAC_TX_CLOCK | uipRCC_MAC_RX_CLOCK );
|
|
|
|
/* Set the MAC address. */
|
|
ETH_MACAddressConfig( ETH_MAC_Address0, ( unsigned char * ) ucMACAddress );
|
|
|
|
/* Use MII mode. */
|
|
AFIO->MAPR &= ~( uipMODE_MII );
|
|
|
|
/* Configure all the GPIO as required for MAC/PHY interfacing. */
|
|
prvSetupEthGPIO();
|
|
|
|
/* Reset the peripheral. */
|
|
ETH_SoftwareReset();
|
|
while( ETH_GetSoftwareResetStatus() == SET );
|
|
|
|
/* Initialise using the whopping big structure. Code space could be saved
|
|
by making this a const struct, however that would mean changes to the
|
|
structure within the library header files could break the code, so for now
|
|
just set everything manually at run time. */
|
|
xEthInit.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable;
|
|
xEthInit.ETH_Watchdog = ETH_Watchdog_Disable;
|
|
xEthInit.ETH_Jabber = ETH_Jabber_Disable;
|
|
xEthInit.ETH_JumboFrame = ETH_JumboFrame_Disable;
|
|
xEthInit.ETH_InterFrameGap = ETH_InterFrameGap_96Bit;
|
|
xEthInit.ETH_CarrierSense = ETH_CarrierSense_Enable;
|
|
xEthInit.ETH_Speed = ETH_Speed_10M;
|
|
xEthInit.ETH_ReceiveOwn = ETH_ReceiveOwn_Disable;
|
|
xEthInit.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
|
|
xEthInit.ETH_Mode = ETH_Mode_HalfDuplex;
|
|
xEthInit.ETH_ChecksumOffload = ETH_ChecksumOffload_Disable;
|
|
xEthInit.ETH_RetryTransmission = ETH_RetryTransmission_Disable;
|
|
xEthInit.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
|
|
xEthInit.ETH_BackOffLimit = ETH_BackOffLimit_10;
|
|
xEthInit.ETH_DeferralCheck = ETH_DeferralCheck_Disable;
|
|
xEthInit.ETH_ReceiveAll = ETH_ReceiveAll_Enable;
|
|
xEthInit.ETH_SourceAddrFilter = ETH_SourceAddrFilter_Disable;
|
|
xEthInit.ETH_PassControlFrames = ETH_PassControlFrames_ForwardPassedAddrFilter;
|
|
xEthInit.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Disable;
|
|
xEthInit.ETH_DestinationAddrFilter = ETH_DestinationAddrFilter_Normal;
|
|
xEthInit.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
|
|
xEthInit.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
|
|
xEthInit.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
|
|
xEthInit.ETH_HashTableHigh = 0x0;
|
|
xEthInit.ETH_HashTableLow = 0x0;
|
|
xEthInit.ETH_PauseTime = 0x0;
|
|
xEthInit.ETH_ZeroQuantaPause = ETH_ZeroQuantaPause_Disable;
|
|
xEthInit.ETH_PauseLowThreshold = ETH_PauseLowThreshold_Minus4;
|
|
xEthInit.ETH_UnicastPauseFrameDetect = ETH_UnicastPauseFrameDetect_Disable;
|
|
xEthInit.ETH_ReceiveFlowControl = ETH_ReceiveFlowControl_Disable;
|
|
xEthInit.ETH_TransmitFlowControl = ETH_TransmitFlowControl_Disable;
|
|
xEthInit.ETH_VLANTagComparison = ETH_VLANTagComparison_16Bit;
|
|
xEthInit.ETH_VLANTagIdentifier = 0x0;
|
|
xEthInit.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Disable;
|
|
xEthInit.ETH_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable;
|
|
xEthInit.ETH_FlushReceivedFrame = ETH_FlushReceivedFrame_Disable;
|
|
xEthInit.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;
|
|
xEthInit.ETH_TransmitThresholdControl = ETH_TransmitThresholdControl_64Bytes;
|
|
xEthInit.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Disable;
|
|
xEthInit.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable;
|
|
xEthInit.ETH_ReceiveThresholdControl = ETH_ReceiveThresholdControl_64Bytes;
|
|
xEthInit.ETH_SecondFrameOperate = ETH_SecondFrameOperate_Disable;
|
|
xEthInit.ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable;
|
|
xEthInit.ETH_FixedBurst = ETH_FixedBurst_Disable;
|
|
xEthInit.ETH_RxDMABurstLength = ETH_RxDMABurstLength_1Beat;
|
|
xEthInit.ETH_TxDMABurstLength = ETH_TxDMABurstLength_1Beat;
|
|
xEthInit.ETH_DescriptorSkipLength = 0x0;
|
|
xEthInit.ETH_DMAArbitration = ETH_DMAArbitration_RoundRobin_RxTx_1_1;
|
|
|
|
xReturn = ETH_Init( &xEthInit, uipPHY_ADDRESS );
|
|
|
|
/* Check a link was established. */
|
|
if( xReturn != pdFAIL )
|
|
{
|
|
/* Rx and Tx interrupts are used. */
|
|
ETH_DMAITConfig( ETH_DMA_IT_NIS | ETH_DMA_IT_R | ETH_DMA_IT_T, ENABLE );
|
|
|
|
/* Only a single Tx descriptor is used. For now it is set to use an Rx
|
|
buffer, but will get updated to point to where ever uip_buf is
|
|
pointing prior to its use. */
|
|
ETH_DMATxDescChainInit( ( void * ) &xTxDescriptor, ( void * ) ucMACBuffers, 1 );
|
|
ETH_DMARxDescChainInit( xRxDescriptors, ( void * ) ucMACBuffers, uipNUM_RX_DESCRIPTORS );
|
|
for( ul = 0; ul < uipNUM_RX_DESCRIPTORS; ul++ )
|
|
{
|
|
/* Ensure received data generates an interrupt. */
|
|
ETH_DMARxDescReceiveITConfig( &( xRxDescriptors[ ul ] ), ENABLE );
|
|
|
|
/* Fix up the addresses used by the descriptors.
|
|
The way ETH_DMARxDescChainInit() is not compatible with the buffer
|
|
declarations in this file. */
|
|
xRxDescriptors[ ul ].Buffer1Addr = ( unsigned long ) &( ucMACBuffers[ ul ][ 0 ] );
|
|
|
|
/* Mark the buffer used by this descriptor as in use. */
|
|
ucBufferInUse[ ul ] = pdTRUE;
|
|
}
|
|
|
|
/* When receiving data, start at the first descriptor. */
|
|
ulNextDescriptor = 0;
|
|
|
|
/* Initialise uip_buf to ensure it points somewhere valid. */
|
|
uip_buf = prvGetNextBuffer();
|
|
|
|
/* SendCount must be initialised to 2 to ensure the Tx descriptor looks
|
|
as if its available (as if it has already been sent twice. */
|
|
xTxDescriptor.SendCount = 2;
|
|
|
|
/* Switch on the interrupts in the NVIC. */
|
|
xNVICInit.NVIC_IRQChannel = uipENET_IRQ_NUM;
|
|
xNVICInit.NVIC_IRQChannelPreemptionPriority = configLIBRARY_KERNEL_INTERRUPT_PRIORITY;
|
|
xNVICInit.NVIC_IRQChannelSubPriority = 0;
|
|
xNVICInit.NVIC_IRQChannelCmd = ENABLE;
|
|
NVIC_Init( &xNVICInit );
|
|
|
|
/* Buffers and descriptors are all set up, now enable the MAC. */
|
|
ETH_Start();
|
|
|
|
/* Let the DMA know there are Rx descriptors available. */
|
|
prvRxDescriptorAvailable();
|
|
}
|
|
|
|
return xReturn;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static unsigned char *prvGetNextBuffer( void )
|
|
{
|
|
portBASE_TYPE x;
|
|
unsigned char *ucReturn = NULL;
|
|
unsigned long ulAttempts = 0;
|
|
|
|
while( ucReturn == NULL )
|
|
{
|
|
/* Look through the buffers to find one that is not in use by
|
|
anything else. */
|
|
for( x = 0; x < uipNUM_BUFFERS; x++ )
|
|
{
|
|
if( ucBufferInUse[ x ] == pdFALSE )
|
|
{
|
|
ucBufferInUse[ x ] = pdTRUE;
|
|
ucReturn = &( ucMACBuffers[ x ][ 0 ] );
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Was a buffer found? */
|
|
if( ucReturn == NULL )
|
|
{
|
|
ulAttempts++;
|
|
|
|
if( ulAttempts >= uipBUFFER_WAIT_ATTEMPTS )
|
|
{
|
|
break;
|
|
}
|
|
|
|
/* Wait then look again. */
|
|
vTaskDelay( uipBUFFER_WAIT_DELAY );
|
|
}
|
|
}
|
|
|
|
return ucReturn;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
unsigned short usGetMACRxData( void )
|
|
{
|
|
unsigned short usReturn;
|
|
|
|
if( ( xRxDescriptors[ ulNextDescriptor ].Status & ETH_DMARxDesc_ES ) != 0 )
|
|
{
|
|
/* Error in Rx. Discard the frame and give it back to the DMA. */
|
|
xRxDescriptors[ ulNextDescriptor ].Status = ETH_DMARxDesc_OWN;
|
|
prvRxDescriptorAvailable();
|
|
|
|
/* No data to return. */
|
|
usReturn = 0UL;
|
|
|
|
/* Start from the next descriptor the next time this function is called. */
|
|
ulNextDescriptor++;
|
|
if( ulNextDescriptor >= uipNUM_RX_DESCRIPTORS )
|
|
{
|
|
ulNextDescriptor = 0UL;
|
|
}
|
|
}
|
|
else if( ( xRxDescriptors[ ulNextDescriptor ].Status & ETH_DMARxDesc_OWN ) == 0 )
|
|
{
|
|
/* Mark the current buffer as free as uip_buf is going to be set to
|
|
the buffer that contains the received data. */
|
|
vReturnBuffer( uip_buf );
|
|
|
|
/* Get the received data length from the top 2 bytes of the Status
|
|
word and the data itself. */
|
|
usReturn = ( unsigned short ) ( ( xRxDescriptors[ ulNextDescriptor ].Status & ETH_DMARxDesc_FL ) >> 16UL );
|
|
uip_buf = ( unsigned char * ) ( xRxDescriptors[ ulNextDescriptor ].Buffer1Addr );
|
|
|
|
/* Allocate a new buffer to the descriptor. */
|
|
xRxDescriptors[ ulNextDescriptor ].Buffer1Addr = ( unsigned long ) prvGetNextBuffer();
|
|
|
|
/* Give the descriptor back to the DMA. */
|
|
xRxDescriptors[ ulNextDescriptor ].Status = ETH_DMARxDesc_OWN;
|
|
prvRxDescriptorAvailable();
|
|
|
|
/* Start from the next descriptor the next time this function is called. */
|
|
ulNextDescriptor++;
|
|
if( ulNextDescriptor >= uipNUM_RX_DESCRIPTORS )
|
|
{
|
|
ulNextDescriptor = 0UL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* No received data at all. */
|
|
usReturn = 0UL;
|
|
}
|
|
|
|
return usReturn;
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void vSendMACData( unsigned short usDataLen )
|
|
{
|
|
unsigned long ulAttempts = 0UL;
|
|
|
|
/* Check to see if the Tx descriptor is free. The check against <2 is to
|
|
ensure the buffer has been sent twice and in so doing preventing a race
|
|
condition with the DMA on the ETH_DMATxDesc_OWN bit. */
|
|
while( ( xTxDescriptor.SendCount < 2 ) && ( xTxDescriptor.Status & ETH_DMATxDesc_OWN ) == ETH_DMATxDesc_OWN )
|
|
{
|
|
/* Wait for the Tx descriptor to become available. */
|
|
vTaskDelay( uipBUFFER_WAIT_DELAY );
|
|
|
|
ulAttempts++;
|
|
if( ulAttempts > uipBUFFER_WAIT_ATTEMPTS )
|
|
{
|
|
/* Something has gone wrong as the Tx descriptor is still in use.
|
|
Clear it down manually, the data it was sending will probably be
|
|
lost. */
|
|
xTxDescriptor.Status &= ~ETH_DMATxDesc_OWN;
|
|
vReturnBuffer( ( unsigned char * ) xTxDescriptor.Buffer1Addr );
|
|
break;
|
|
}
|
|
}
|
|
|
|
/* Setup the Tx descriptor for transmission. */
|
|
xTxDescriptor.SendCount = 0;
|
|
xTxDescriptor.Buffer1Addr = ( unsigned long ) uip_buf;
|
|
xTxDescriptor.ControlBufferSize = ( unsigned long ) usDataLen;
|
|
xTxDescriptor.Status = ETH_DMATxDesc_OWN | ETH_DMATxDesc_LS | ETH_DMATxDesc_FS | ETH_DMATxDesc_TER | ETH_DMATxDesc_TCH | ETH_DMATxDesc_IC;
|
|
ETH_DMA->DMASR = ETH_DMASR_TBUS;
|
|
ETH_DMA->DMATPDR = 0;
|
|
|
|
/* uip_buf is being sent by the Tx descriptor. Allocate a new buffer. */
|
|
uip_buf = prvGetNextBuffer();
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
static void prvSetupEthGPIO( void )
|
|
{
|
|
GPIO_InitTypeDef xEthInit;
|
|
|
|
/* Remap MAC IO. */
|
|
AFIO->MAPR |= ( uipREMAP_MAC_IO );
|
|
|
|
/* Set PA2, PA8, PB5, PB8, PB11, PB12, PB13, PC1 and PC2 for Ethernet
|
|
interfacing. */
|
|
xEthInit.GPIO_Pin = GPIO_Pin_2;/* | GPIO_Pin_8; This should be set when the 25MHz is generated by MCO. */
|
|
xEthInit.GPIO_Speed = GPIO_Speed_50MHz;
|
|
xEthInit.GPIO_Mode = GPIO_Mode_AF_PP;
|
|
GPIO_Init( GPIOA, &xEthInit );
|
|
|
|
xEthInit.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13; /*5*/
|
|
GPIO_Init( GPIOB, &xEthInit );
|
|
|
|
xEthInit.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
|
|
GPIO_Init( GPIOC, &xEthInit );
|
|
|
|
|
|
/* Configure PA0, PA1, PA3, PB10, PC3, PD8, PD9, PD10, PD11 and PD12 as
|
|
inputs. */
|
|
xEthInit.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_3;
|
|
xEthInit.GPIO_Mode = GPIO_Mode_IN_FLOATING;
|
|
GPIO_Init( GPIOA, &xEthInit );
|
|
|
|
xEthInit.GPIO_Pin = GPIO_Pin_10;
|
|
GPIO_Init( GPIOB, &xEthInit );
|
|
|
|
xEthInit.GPIO_Pin = GPIO_Pin_3;
|
|
GPIO_Init( GPIOC, &xEthInit );
|
|
|
|
xEthInit.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12;
|
|
GPIO_Init( GPIOD, &xEthInit );
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void vReturnBuffer( unsigned char *pucBuffer )
|
|
{
|
|
unsigned long ul;
|
|
|
|
/* Mark a buffer as free for use. */
|
|
for( ul = 0; ul < uipNUM_BUFFERS; ul++ )
|
|
{
|
|
if( ucMACBuffers[ ul ] == pucBuffer )
|
|
{
|
|
ucBufferInUse[ ul ] = pdFALSE;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void vMAC_ISR( void )
|
|
{
|
|
unsigned long ulStatus;
|
|
extern xSemaphoreHandle xEMACSemaphore;
|
|
long xHigherPriorityTaskWoken = pdFALSE;
|
|
|
|
/* What caused the interrupt? */
|
|
ulStatus = ETH_DMA->DMASR;
|
|
|
|
/* Clear everything before leaving. */
|
|
ETH_DMA->DMASR = ulStatus;
|
|
|
|
if( ulStatus & ETH_DMA_IT_R )
|
|
{
|
|
/* Data was received. Ensure the uIP task is not blocked as data has
|
|
arrived. */
|
|
xSemaphoreGiveFromISR( xEMACSemaphore, &xHigherPriorityTaskWoken );
|
|
}
|
|
|
|
if( ulStatus & ETH_DMA_IT_T )
|
|
{
|
|
/* Data was transmitted. */
|
|
if( xTxDescriptor.SendCount == 0 )
|
|
{
|
|
/* Send again! */
|
|
( xTxDescriptor.SendCount )++;
|
|
|
|
xTxDescriptor.Status = ETH_DMATxDesc_OWN | ETH_DMATxDesc_LS | ETH_DMATxDesc_FS | ETH_DMATxDesc_TER | ETH_DMATxDesc_TCH | ETH_DMATxDesc_IC;
|
|
ETH_DMA->DMASR = ETH_DMASR_TBUS;
|
|
ETH_DMA->DMATPDR = 0;
|
|
}
|
|
else
|
|
{
|
|
/* The Tx buffer is no longer required. */
|
|
vReturnBuffer( ( unsigned char * ) xTxDescriptor.Buffer1Addr );
|
|
}
|
|
}
|
|
|
|
/* If xSemaphoreGiveFromISR() unblocked a task, and the unblocked task has
|
|
a higher priority than the currently executing task, then
|
|
xHigherPriorityTaskWoken will have been set to pdTRUE and this ISR should
|
|
return directly to the higher priority unblocked task. */
|
|
portEND_SWITCHING_ISR( xHigherPriorityTaskWoken );
|
|
}
|
|
|