Добрый день
Скопировал схему STM32F4DIS-BB Discove ( Ethernet, LAN8720 ) в свой проект.
Мой проект работает с RTX ( uVision), STM32F407VGT6.
Hardware часть в полном порядке. Я загрузил пример с STM32F4DIS-BB в свою плату и плата отвечаут на ping и получает IP по DHCP.
Я так понимаю, что в своем проекте лучше использовать стек от Keil ( RL-TCPNet).
Когда я запускаю свое проект ( см. код ниже ), плата отвечат "DHCP Fail". Проблем с компиляцией нет. Читаются все регистры LAN8720.
Driver LAN8720 взят из стандартной библиотеки ( кроме инициализации ethernet ).
Сам код продолжает работать без проблем.
Как проверить работоспособность RL-TCPnet?
Что в настройках упущенно или сделано неправильно?
Две строки ниже добавил сам. Стандартная функция неправильно считает делитель частоты
ETH->MACMIIAR &= MACMIIAR_CR_MASK;
ETH->MACMIIAR |= 0x00000004 ;
файл Ethernet_V1.c:
CODE
#include <RTL.h>
#include "STM32F4xx.h"
#include "Ethernet_V1.h"
#include "stm32f4xx_rtc.h"
#include "stm32f4x7_eth.h"
#include "ETH_STM32F4xx.h"
#include <Net_Config.h>
#include "..\Project_Setup.h"
#include "..\Project_Definitions.h"
//==========================================================
// Task to init Ethernet
//==========================================================
__task void EthernetInit (void)
{
init_TcpNet ();
os_tsk_create ( tcp_tick, 20 );
t_ETH_Task = os_tsk_create_user ( Tcp_Task, 0, &tcp_stack, sizeof(tcp_stack));
// PutDec_Bash (sizeof(OS_FRAME));
while ( TCP_23_State != 3 )
{
os_dly_wait ( 2000 );
Send_String_Bash ("L");
}
/*
#define TCP_TYPE_SERVER 0x01 // Socket Type Server (open for listening)
#define TCP_TYPE_CLIENT 0x02 // Socket Type Client (initiate connect)
#define TCP_TYPE_DELAY_ACK 0x04 // Socket Type Delayed Acknowledge
#define TCP_TYPE_FLOW_CTRL 0x08 // Socket Type Flow Control
#define TCP_TYPE_KEEP_ALIVE 0x10 // Socket Type Keep Alive
#define TCP_TYPE_CLIENT_SERVER (TCP_TYPE_SERVER | TCP_TYPE_CLIENT)
*/
socket_tcp = tcp_get_socket(TCP_TYPE_SERVER, 0, 20, tcp_callback);
// Send_String_Bash ("S:");
// PutDec_Bash ( socket_tcp );
if (socket_tcp!= 0)
{
if(tcp_listen(socket_tcp, 23 )==__TRUE)
Send_String_Bash ("\nListen Ready");
else
Send_String_Bash ("\nListen Fail");
}
os_tsk_delete_self ();
} //__task void EthernetInit (void)
U16 tcp_callback (U8 soc, U8 event, U8 *ptr, U16 par)
{
if (soc != socket_tcp) { // Error
return(0);
}
Send_String_Bash ("\nOpen:");
PutDec_Bash ( event );
switch(event)
{
case TCP_EVT_DATA:
break;
case TCP_EVT_CONREQ:
return (1);
case TCP_EVT_CONNECT:
Send_String_Bash ("\nConnected");
break;
case TCP_EVT_CLOSE:
Send_String_Bash ("\nDisconnected");
// tcp_close (soc);
// return (1);
break;
case TCP_EVT_ABORT:
break;
case TCP_EVT_ACK:
break;
default:
break;
}
return(0);
}
//=============================================================
// ETH routing Task
//=============================================================
__task void Tcp_Task (void)
{
dhcp_tout = DHCP_TOUT;
for (;;)
{
os_evt_wait_or ( 0x0001 | 0x0002 , 0xFFFF );
while ( main_TcpNet() == __TRUE ) continue;//
dhcp_check ();
}
}
//=============================================================
// Ethernet Tick routine
//=============================================================
/* System tick timer task */
os_itv_set (100);
for (;;)
{
os_itv_wait();
timer_tick ();
tick = __TRUE;
os_evt_set ( 0x0001, t_ETH_Task );
}
//============================================================
//
//============================================================
static void dhcp_check ( void )
{
/* Monitor DHCP IP address assignment. */
if (tick == __FALSE || dhcp_tout == 0) {
return;
}
tick = __FALSE;
if (mem_test (&MY_IP, 0, IP_ADRLEN) == __FALSE && !(dhcp_tout & 0x80000000))
{
// Success, DHCP has already got the IP address.
dhcp_tout = 0;
Send_String_Bash ("\nIP Received");
PutDec_Bash ( MY_IP[0] );
Send_String_Bash (".");
PutDec_Bash ( MY_IP[1] );
Send_String_Bash (".");
PutDec_Bash ( MY_IP[2] );
Send_String_Bash (".");
PutDec_Bash ( MY_IP[3] );
Send_String_Bash (" ");
TCP_23_State |= 2;
// PutDec_Bash ( TCP_23_State );
return;
}
if (--dhcp_tout == 0)
{
// A timeout, disable DHCP and use static IP address.
// dhcp_disable ();
// if ( ErrorShowEnabled == 1 )
{
Send_String_Bash ("\nTCP>DHCP Fail");
}
dhcp_tout = 30 | 0x80000000;
return;
}
if (dhcp_tout == 0x80000000)
{
dhcp_tout = 0;
Send_String_Bash ("\nIP Address");
PutDec_Bash ( MY_IP[0] );
Send_String_Bash (".");
PutDec_Bash ( MY_IP[1] );
Send_String_Bash (".");
PutDec_Bash ( MY_IP[2] );
Send_String_Bash (".");
PutDec_Bash ( MY_IP[3] );
Send_String_Bash (" ");
// TCP_23_State |= 2;
// PutDec_Bash ( TCP_23_State );
}
}
/*-----------------------------------------------------------------------------
* ENET Ethernet Driver Functions
*-----------------------------------------------------------------------------
* Required functions for Ethernet driver module:
* a. Polling mode: - void init_ethernet ()
* - void send_frame (OS_FRAME *frame)
* - void poll_ethernet (void)
* b. Interrupt mode: - void init_ethernet ()
* - void send_frame (OS_FRAME *frame)
* - void int_enable_eth ()
* - void int_disable_eth ()
* - interrupt function
*----------------------------------------------------------------------------*/
/*--------------------------- init_ethernet ----------------------------------*/
void init_ethernet (void)
{
GPIO_InitTypeDef GPIO_InitStructure;
//Configure the GPIO for ethernet controller ======================================================
/* Enable GPIOs clocks */
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOE, ENABLE);
/* Enable SYSCFG clock */
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* MII/RMII Media interface selection --------------------------------------*/
SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
/* Ethernet pins configuration ************************************************/
/*
ETH_MDIO --------------> PA2
ETH_MDC ---------------> PC1
ETH_RMII_REF_CLK-------> PA1
ETH_RMII_CRS_DV -------> PA7
// ETH_MII_RX_ER -------> PB10 - not using
ETH_RMII_RXD0 -------> PC4
ETH_RMII_RXD1 -------> PC5
ETH_RMII_TX_EN -------> PB11
ETH_RMII_TXD0 -------> PB12
ETH_RMII_TXD1 -------> PB13
ETH_RST_PIN -------> PE2
*/
/* Configure PA1,PA2 and PA7 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2 | GPIO_Pin_7;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL ;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH);
GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH);
/* Configure PB10,PB11,PB12 and PB13 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
GPIO_Init(GPIOB, &GPIO_InitStructure);
// GPIO_PinAFConfig(GPIOB, GPIO_PinSource10, GPIO_AF_ETH);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_ETH);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource12, GPIO_AF_ETH);
GPIO_PinAFConfig(GPIOB, GPIO_PinSource13, GPIO_AF_ETH);
/* Configure PC1, PC4 and PC5 */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_Init(GPIOC, &GPIO_InitStructure);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH);
GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH);
/* Configure the PHY RST pin */
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_OUT;
GPIO_InitStructure.GPIO_OType = GPIO_OType_PP;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_UP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOE, &GPIO_InitStructure);
GPIO_ResetBits(GPIOE, GPIO_Pin_2);
os_dly_wait ( 10 );
GPIO_SetBits(GPIOE, GPIO_Pin_2);
os_dly_wait ( 1 );
// Enable ETHERNET clock
RCC_AHB1PeriphClockCmd (RCC_AHB1Periph_ETH_MAC | RCC_AHB1Periph_ETH_MAC_Tx | RCC_AHB1Periph_ETH_MAC_Rx, ENABLE);
// Reset ETHERNET on AHB Bus
ETH_DeInit();
// Software reset
ETH_SoftwareReset();
os_dly_wait ( 1 );
ETH_Error = 0;
// Wait for software reset
while (ETH_GetSoftwareResetStatus() == SET)
{
if ( ETH_Error++ == 20 ) break;
os_dly_wait ( 1 );
}
//Check is Link UP
while ( ( ETH_ReadPHYRegister( LAN8720_PHY_ADDRESS, PHY_BSR) & PHY_Linked_Status ) == 0 )
{
// Send_String_Bash ("Hello");
// PutDec_Bash ( ETH_ReadPHYRegister(LAN8720_PHY_ADDRESS, PHY_BSR) & PHY_Linked_Status );
os_dly_wait ( 50 );
}
if ( ETH_Error == 0 )
{
// Initialize the ETH ethernet controller.
// ETHERNET Configuration --------------------------------------------------//
// Call ETH_StructInit if you don't like to configure all ETH_InitStructure parameter //
ETH_StructInit(Ð_InitStructure);
// Fill ETH_InitStructure parametrs //
//------------------------ MAC -----------------------------------//
ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable;
// ETH_InitStructure.ETH_Speed = ETH_Speed_100M;
// ETH_InitStructure.ETH_Mode = ETH_Mode_FullDuplex;
ETH_InitStructure.ETH_LoopbackMode = ETH_LoopbackMode_Disable;
ETH_InitStructure.ETH_RetryTransmission = ETH_RetryTransmission_Disable;
ETH_InitStructure.ETH_AutomaticPadCRCStrip = ETH_AutomaticPadCRCStrip_Disable;
ETH_InitStructure.ETH_ReceiveAll = ETH_ReceiveAll_Disable;
ETH_InitStructure.ETH_BroadcastFramesReception = ETH_BroadcastFramesReception_Enable;
ETH_InitStructure.ETH_PromiscuousMode = ETH_PromiscuousMode_Disable;
ETH_InitStructure.ETH_MulticastFramesFilter = ETH_MulticastFramesFilter_Perfect;
ETH_InitStructure.ETH_UnicastFramesFilter = ETH_UnicastFramesFilter_Perfect;
//#ifdef CHECKSUM_BY_HARDWARE
ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
//#endif
//------------------------ DMA -----------------------------------//
// When we use the Checksum offload feature, we need to enable the Store and Forward mode:
//the store and forward guarantee that a whole frame is stored in the FIFO, so the MAC can insert/verify the checksum,
//if the checksum is OK the DMA can handle the frame otherwise the frame is dropped
ETH_InitStructure.ETH_DropTCPIPChecksumErrorFrame = ETH_DropTCPIPChecksumErrorFrame_Enable;
ETH_InitStructure.ETH_ReceiveStoreForward = ETH_ReceiveStoreForward_Enable;
ETH_InitStructure.ETH_TransmitStoreForward = ETH_TransmitStoreForward_Enable;
ETH_InitStructure.ETH_ForwardErrorFrames = ETH_ForwardErrorFrames_Disable;
ETH_InitStructure.ETH_ForwardUndersizedGoodFrames = ETH_ForwardUndersizedGoodFrames_Disable;
ETH_InitStructure.ETH_SecondFrameOperate = ETH_SecondFrameOperate_Enable;
ETH_InitStructure.ETH_AddressAlignedBeats = ETH_AddressAlignedBeats_Enable;
ETH_InitStructure.ETH_FixedBurst = ETH_FixedBurst_Enable;
ETH_InitStructure.ETH_RxDMABurstLength = ETH_RxDMABurstLength_32Beat;
ETH_InitStructure.ETH_TxDMABurstLength = ETH_TxDMABurstLength_32Beat;
ETH_InitStructure.ETH_DMAArbitration = ETH_DMAArbitration_RoundRobin_RxTx_2_1;
/* Configure Ethernet */
EthInitStatus = ETH_Init(Ð_InitStructure, LAN8720_PHY_ADDRESS );
/* HCLK Clock range 120-168MHz. */
ETH->MACMIIAR &= MACMIIAR_CR_MASK;
ETH->MACMIIAR |= 0x00000004 ;
// MAC address filtering, accept multicast packets.
ETH->MACFFR = MFFR_HPF | MFFR_PAM;
ETH->MACFCR = MFCR_ZQPD;
// Initialize Tx and Rx DMA Descriptors
rx_descr_init ();
tx_descr_init ();
// Flush FIFO, start DMA Tx and Rx
ETH->DMAOMR = DOMR_FTF | DOMR_ST | DOMR_SR;
// Enable receiver and transmiter
ETH->MACCR |= MCR_TE | MCR_RE;
// Reset all interrupts
ETH->DMASR = 0xFFFFFFFF;
// Enable Rx and Tx interrupts.
ETH->DMAIER = INT_NISE | INT_AISE | INT_RBUIE | INT_RIE; //
TCP_23_State |= 1;
} // end of if ( ETH_Error == 0 )
else
{
EthInitStatus = 2;
if ( ErrorShowEnabled == 1 )
{
// Send_String_Bash ("\nETH>Init Error ");
}
} //end of else
} //end of void init_ethernet (void)
//==============================================================
//
//==============================================================
void ETH_IRQHandler (void)
{
fetch_packet ();
isr_evt_set ( 0x0002, t_ETH_Task );//Tcp_Task);
// Clear the interrupt flags.
// Clear the Eth DMA Rx IT pending bits
}
/*--------------------------- int_enable_eth ---------------------------------*/
void int_enable_eth (void) {
/* Ethernet Interrupt Enable function. */
// NVIC->ISER[1] = 1 << 29;
}
/*--------------------------- int_disable_eth --------------------------------*/
void int_disable_eth (void) {
/* Ethernet Interrupt Disable function. */
// NVIC->ICER[1] = 1 << 29;
}
//-------------------------- send_frame -------------------------------------
void send_frame (OS_FRAME *frame)
{
// Send frame to ETH ethernet controller
U32 *sp,*dp;
U32 i,j;
j = TxBufIndex;
// Wait until previous packet transmitted.
while (Tx_Desc[j].CtrlStat & DMA_TX_OWN);
sp = (U32 *)&frame->data[0];
dp = (U32 *)(Tx_Desc[j].Addr & ~3);
// Copy frame data to ETH IO buffer.
for (i = (frame->length + 3) >> 2; i; i--) {
*dp++ = *sp++;
}
Tx_Desc[j].Size = frame->length;
Tx_Desc[j].CtrlStat |= DMA_TX_OWN;
if (++j == NUM_TX_BUF) j = 0;
TxBufIndex = j;
// Start frame transmission.
ETH->DMASR = DSR_TPSS;
ETH->DMATPDR = 0;
}
//=======================================================
//
//=======================================================
static void fetch_packet ( void )
{
OS_FRAME *frame;
U32 i, RxLen;
U32 *sp,*dp;
i = RxBufIndex;
do {
if (Rx_Desc[i].Stat & DMA_RX_ERROR_MASK) {
ETH_Err = 1;
goto rel;
}
/*
if ((Rx_Desc[i].Stat & DMA_RX_SEG_MASK) != DMA_RX_SEG_MASK) {
ETH_Err = 2;
goto rel;
}
*/
RxLen = ((Rx_Desc[i].Stat >> 16) & 0x3FFF) - 4;
if (RxLen > ETH_MTU) {
ETH_Err = 3;
/* Packet too big, ignore it and free buffer. */
goto rel;
}
/* Flag 0x80000000 to skip sys_error() call when out of memory. */
frame = alloc_mem (RxLen | 0x80000000);
/* if 'alloc_mem()' has failed, ignore this packet. */
if (frame != NULL) {
sp = (U32 *)(Rx_Desc[i].Addr & ~3);
dp = (U32 *)&frame->data[0];
for (RxLen = (RxLen + 3) >> 2; RxLen; RxLen--) {
*dp++ = *sp++;
}
put_in_queue (frame);
}
else ETH_Err = 4;
/* Release this frame from ETH IO buffer. */
rel:Rx_Desc[i].Stat = DMA_RX_OWN;
if (++i == NUM_RX_BUF) i = 0;
RxBufIndex = i;
}
while (!(Rx_Desc[i].Stat & DMA_RX_OWN));
RxBufIndex = i;
if (ETH->DMASR & INT_RBUIE) {
/* Receive buffer unavailable, resume DMA */
ETH->DMASR = INT_RBUIE;
ETH->DMARPDR = 0;
}
/* Clear pending interrupt bits */
ETH->DMASR = INT_NISE | INT_RIE;
}
/*--------------------------- rx_descr_init ----------------------------------*/
static void rx_descr_init (void) {
/* Initialize Receive DMA Descriptor array. */
U32 i,next;
RxBufIndex = 0;
for (i = 0, next = 0; i < NUM_RX_BUF; i++) {
if (++next == NUM_RX_BUF) next = 0;
Rx_Desc[i].Stat = DMA_RX_OWN;
Rx_Desc[i].Ctrl = DMA_RX_RCH | ETH_BUF_SIZE;
Rx_Desc[i].Addr = (U32)&rx_buf[i];
Rx_Desc[i].Next = (U32)&Rx_Desc[next];
}
ETH->DMARDLAR = (U32)&Rx_Desc[0];
}
/*--------------------------- tx_descr_init ----------------------------------*/
static void tx_descr_init (void) {
/* Initialize Transmit DMA Descriptor array. */
U32 i,next;
TxBufIndex = 0;
for (i = 0, next = 0; i < NUM_TX_BUF; i++) {
if (++next == NUM_TX_BUF) next = 0;
Tx_Desc[i].CtrlStat = DMA_TX_TCH | DMA_TX_LS | DMA_TX_FS;
Tx_Desc[i].Addr = (U32)&tx_buf[i];
Tx_Desc[i].Next = (U32)&Tx_Desc[next];
}
ETH->DMATDLAR = (U32)&Tx_Desc[0];
}
Сообщение отредактировал IgorKossak - Jan 22 2014, 10:27
Причина редактирования: [codebox] для длинного кода, [code] - для короткого!!!