📄 enet_freertos.c
字号:
/*
FreeRTOS.org V5.0.3 - Copyright (C) 2003-2008 Richard Barry.
This file is part of the FreeRTOS.org distribution.
FreeRTOS.org is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
FreeRTOS.org 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.org; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
A special exception to the GPL can be applied should you wish to distribute
a combined work that includes FreeRTOS.org, without being obliged to provide
the source code for any proprietary components. See the licensing section
of http://www.FreeRTOS.org for full details of how and when the exception
can be applied.
***************************************************************************
See http://www.FreeRTOS.org for documentation, latest information, license
and contact details. Please ensure to read the configuration and relevant
port sections of the online documentation.
***************************************************************************
*/
/* Kernel includes. */
#include "FreeRTOS.h"
#include "semphr.h"
#include "task.h"
#include "common.h"
/* Demo includes. */
#include "eth_phy.h"
#include "enet.h"
#include "mii.h"
/*FSL: specific includes*/
#include "enet_freertos.h"
/* uIP includes. */
#include "uip.h"
#include "uip_arp.h"
/* PHY hardware specifics. */
#define PHY_STATUS ( 0x1F )
#define PHY_DUPLEX_STATUS ( 4<<2 )
#define PHY_SPEED_STATUS ( 1<<2 )
/* Delay between polling the PHY to see if a link has been established. */
#define enetLINK_DELAY ( 500 / portTICK_RATE_MS )
/* Very short delay to use when waiting for the Tx to finish with a buffer if
we run out of Rx buffers. */
#define enetMINIMAL_DELAY ( 2 / portTICK_RATE_MS )
/* The Tx re-uses the Rx buffers and only has one descriptor. */
#define enetNUM_TX_DESCRIPTORS ( 1 )
/*-----------------------------------------------------------*/
/* The semaphore used to wake the uIP task when data arrives. */
xSemaphoreHandle xENETSemaphore = NULL;
extern int periph_clk_khz;
/* The buffer used by the uIP stack. In this case the pointer is used to
point to one of the Rx buffers to avoid having to copy the Rx buffer into
the uIP buffer. */
unsigned portCHAR *uip_buf;
/* The DMA descriptors. These are char arrays to allow us to align them
correctly. */
static unsigned portCHAR xENETTxDescriptors_unaligned[ ( enetNUM_TX_DESCRIPTORS * sizeof( NBUF ) ) + 16 ];
static unsigned portCHAR xENETRxDescriptors_unaligned[ ( configNUM_ENET_RX_BUFFERS * sizeof( NBUF ) ) + 16 ];
static NBUF *pxENETTxDescriptor;
static NBUF *xENETRxDescriptors;
/* The DMA buffer. THis is a char arrays to allow it to be aligned correctly. */
static unsigned portCHAR ucENETRxBuffers[ ( configNUM_ENET_RX_BUFFERS * configENET_BUFFER_SIZE ) + 16 ];
static unsigned portBASE_TYPE uxNextRxBuffer = 0;
#if 1 //CW10
uint32_t __REV(uint32_t value)
{
uint32_t result=0;
__asm volatile ("rev %0, %1" : "=r" (result) : "r" (value) );
return(result);
}
__asm int32_t __REVSH(int16_t value)
{
revsh r0, r0
bx lr
}
#endif //CW10
/*-----------------------------------------------------------*/
static void prvInitialiseENETBuffers( void )
{
unsigned portBASE_TYPE ux;
unsigned portCHAR *pcBufPointer;
/* Set the pointer to a correctly aligned address. */
pcBufPointer = &( xENETTxDescriptors_unaligned[ 0 ] );
while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )
{
pcBufPointer++;
}
pxENETTxDescriptor = ( NBUF * ) pcBufPointer;
/* Likewise the pointer to the Tx descriptor. */
pcBufPointer = &( xENETRxDescriptors_unaligned[ 0 ] );
while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )
{
pcBufPointer++;
}
xENETRxDescriptors = ( NBUF * ) pcBufPointer;
/* There is no Tx buffer as the Rx buffer is reused. */
pxENETTxDescriptor->length = 0;
pxENETTxDescriptor->status = 0;
#ifdef ENHANCED_BD
pxENETTxDescriptor->ebd_status = TX_BD_IINS | TX_BD_PINS;
#endif
/* Align the Rx buffers. */
pcBufPointer = &( ucENETRxBuffers[ 0 ] );
while( ( ( unsigned portLONG ) pcBufPointer & 0x0fUL ) != 0 )
{
pcBufPointer++;
}
/* Then fill in the Rx descriptors. */
for( ux = 0; ux < configNUM_ENET_RX_BUFFERS; ux++ )
{
xENETRxDescriptors[ ux ].status = RX_BD_E;
xENETRxDescriptors[ ux ].length = 0;
#ifdef NBUF_LITTLE_ENDIAN
xENETRxDescriptors[ ux ].data = (uint8_t *)__REV((uint32_t)pcBufPointer);
#else
xENETRxDescriptors[ ux ].data = pcBufPointer;
#endif
pcBufPointer += configENET_BUFFER_SIZE;
#ifdef ENHANCED_BD
xENETRxDescriptors[ ux ].bdu = 0x00000000;
xENETRxDescriptors[ ux ].ebd_status = RX_BD_INT;
#endif
}
/* Set the wrap bit in the last descriptors to form a ring. */
xENETRxDescriptors[ configNUM_ENET_RX_BUFFERS - 1 ].status |= RX_BD_W;
/* We start with descriptor 0. */
uxNextRxBuffer = 0;
}
/*-----------------------------------------------------------*/
void vInitENET( void )
{
/*unsigned portLONG*/ int usData;
struct uip_eth_addr xAddr;
const unsigned portCHAR ucMACAddress[6] =
{
configMAC_ADDR0, configMAC_ADDR1,configMAC_ADDR2,configMAC_ADDR3,configMAC_ADDR4,configMAC_ADDR5
};
/* Enable the ENET clock. */
SIM_SCGC2 |= SIM_SCGC2_ENET_MASK;
/*FSL: allow concurrent access to MPU controller. Example: ENET uDMA to SRAM, otherwise bus error*/
MPU_CESR = 0;
prvInitialiseENETBuffers();
/* Create the semaphore used to wake the uIP task when data arrives. */
vSemaphoreCreateBinary( xENETSemaphore );
/* Set the MAC address within the stack. */
for( usData = 0; usData < 6; usData++ )
{
xAddr.addr[ usData ] = ucMACAddress[ usData ];
}
uip_setethaddr( xAddr );
/* Set the Reset bit and clear the Enable bit */
ENET_ECR = ENET_ECR_RESET_MASK;
/* Wait at least 8 clock cycles */
for( usData = 0; usData < 10; usData++ )
{
asm( "NOP" );
}
/*FSL: start MII interface*/
mii_init(0, periph_clk_khz/1000/*MHz*/);
//enet_interrupt_routine
set_irq_priority (76, 6);
enable_irq(76);//ENET xmit interrupt
//enet_interrupt_routine
set_irq_priority (77, 6);
enable_irq(77);//ENET rx interrupt
//enet_interrupt_routine
set_irq_priority (78, 6);
enable_irq(78);//ENET error and misc interrupts
/*
* Make sure the external interface signals are enabled
*/
PORTB_PCR0 = PORT_PCR_MUX(4);//GPIO;//RMII0_MDIO/MII0_MDIO
PORTB_PCR1 = PORT_PCR_MUX(4);//GPIO;//RMII0_MDC/MII0_MDC
#if configUSE_MII_MODE
PORTA_PCR14 = PORT_PCR_MUX(4);//RMII0_CRS_DV/MII0_RXDV
#if 0
PORTA_PCR5 = PORT_PCR_MUX(4);//RMII0_RXER/MII0_RXER
#else
PORTA_PCR5 = (0|PORT_PCR_MUX(1)|PORT_PCR_PE_MASK|!PORT_PCR_PS_MASK);//GPIO pull down
#endif
PORTA_PCR12 = PORT_PCR_MUX(4);//RMII0_RXD1/MII0_RXD1
PORTA_PCR13 = PORT_PCR_MUX(4);//RMII0_RXD0/MII0_RXD0
PORTA_PCR15 = PORT_PCR_MUX(4);//RMII0_TXEN/MII0_TXEN
PORTA_PCR16 = PORT_PCR_MUX(4);//RMII0_TXD0/MII0_TXD0
PORTA_PCR17 = PORT_PCR_MUX(4);//RMII0_TXD1/MII0_TXD1
PORTA_PCR11 = PORT_PCR_MUX(4);//MII0_RXCLK
PORTA_PCR25 = PORT_PCR_MUX(4);//MII0_TXCLK
PORTA_PCR9 = PORT_PCR_MUX(4);//MII0_RXD3
PORTA_PCR10 = PORT_PCR_MUX(4);//MII0_RXD2
PORTA_PCR28 = PORT_PCR_MUX(4);//MII0_TXER
PORTA_PCR24 = PORT_PCR_MUX(4);//MII0_TXD2
PORTA_PCR26 = PORT_PCR_MUX(4);//MII0_TXD3
PORTA_PCR27 = PORT_PCR_MUX(4);//MII0_CRS
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -