yanvasilij wrote on Monday, September 19, 2016:
Hello!
I am trying to create FreeRTOS+tcp simple network interfaces. I created my own NetworkInterface.c with standard peripheral library and run FreeRTOS_IPInit(). Then I tryed ping my board and did’not get ping answer. ETH_IRQHandler occures, all program doesn’t crash.
MCU - STM32F429
compiler - arm-none-eaby-gcc
NetworkInterface.c:
/* Standard includes. */
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
/* FreeRTOS includes. */
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_IP_Private.h"
#include "NetworkBufferManagement.h"
#include "stm32f4x7_eth.h"
#include "NetworkInterfaceDefs.h"
/* ST includes. */
#include "stm32f4xx.h"
/**********************************************************************************
* prototypes
**********************************************************************************/
static void prvEMACHandlerTask( void *pvParameters );
/**********************************************************************************
* vars
**********************************************************************************/
static TaskHandle_t xEMACTaskHandle = NULL;
/* Ethernet Rx & Tx DMA Descriptors */
extern ETH_DMADESCTypeDef DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB];
/* Ethernet Driver Receive buffers */
extern uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE];
/* Ethernet Driver Transmit buffers */
extern uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE];
/* Global pointer for last received frame infos */
extern ETH_DMA_Rx_Frame_infos *DMA_RX_FRAME_infos;
/**********************************************************************************
* static funs
**********************************************************************************/
static void resetPhy (void)
{
GPIO_InitTypeDef gpioInit;
unsigned int some;
gpioInit.GPIO_Mode = GPIO_Mode_OUT;
gpioInit.GPIO_OType = GPIO_OType_PP;
gpioInit.GPIO_Pin = GPIO_Pin_12;
gpioInit.GPIO_PuPd = GPIO_PuPd_NOPULL;
gpioInit.GPIO_Speed = GPIO_Low_Speed;
GPIO_Init(GPIOH, &gpioInit);
GPIO_WriteBit(GPIOH, GPIO_Pin_12, Bit_RESET);
some=1000000;
while (some) some--;
GPIO_WriteBit(GPIOH, GPIO_Pin_12, Bit_SET);
}
static void initEthGpios (void)
{
GPIO_InitTypeDef gpioInit;
unsigned int some;
RCC->AHB1ENR |= 0x00000010; //GPIOE enable clock
RCC->AHB1ENR |= 0x00000001; //GPIOA enable clock
RCC->AHB1ENR |= 0x00000002; //GPIOB enable clock
RCC->AHB1ENR |= 0x00000004; //GPIOC enable clock
RCC->AHB1ENR |= 0x00000040; //GPIOG enable clock
RCC->AHB1ENR |= 0x00000080; //GPIOH enable clock
gpioInit.GPIO_Mode = GPIO_Mode_OUT;
gpioInit.GPIO_OType = GPIO_OType_PP;
gpioInit.GPIO_Pin = GPIO_Pin_12;
gpioInit.GPIO_PuPd = GPIO_PuPd_NOPULL;
gpioInit.GPIO_Speed = GPIO_Low_Speed;
GPIO_Init(GPIOH, &gpioInit);
GPIO_WriteBit(GPIOH, GPIO_Pin_12, Bit_RESET);
some=1000000;
while (some) some--;
GPIO_WriteBit(GPIOH, GPIO_Pin_12, Bit_SET);
/* Enable System configuration controller clock */
RCC->APB2ENR |= (1 << 14);
/* Reset Ethernet MAC */
RCC->AHB1RSTR |= 0x02000000;
SYSCFG->PMC |= (1 << 23);
RCC->AHB1RSTR &= ~0x02000000;
RCC->AHB1ENR |= 0x1E000047;
/* Configure Port A ethernet pins (PA.1, PA.2, PA.7) */
GPIOA->MODER &= ~0x0000C03C;
GPIOA->MODER |= 0x00008028; /* Pins to alternate function */
GPIOA->OTYPER &= ~0x00000086; /* Pins in push-pull mode */
GPIOA->OSPEEDR |= 0x0000C03C; /* Slew rate as 100MHz pin */
GPIOA->PUPDR &= ~0x0000C03C; /* No pull up, no pull down */
GPIOA->AFR[0] &= ~0xF0000FF0;
GPIOA->AFR[0] |= 0xB0000BB0; /* Pins to AF11 (Ethernet) */
/* Configure Port C ethernet pins (PC.1, PC.4, PC.5) */
GPIOC->MODER &= ~0x00000F0C;
GPIOC->MODER |= 0x00000A08; /* Pins to alternate function */
GPIOC->OTYPER &= ~0x00000032; /* Pins in push-pull mode */
GPIOC->OSPEEDR |= 0x00000F0C; /* Slew rate as 100MHz pin */
GPIOC->PUPDR &= ~0x00000F0C; /* No pull up, no pull down */
GPIOC->AFR[0] &= ~0x00FF00F0;
GPIOC->AFR[0] |= 0x00BB00B0; /* Pins to AF11 (Ethernet) */
/* Configure Port G ethernet pins (PB.12, PB.13) */
GPIOB->MODER &= ~0x0F000000;
GPIOB->MODER |= 0x0A000000; /* Pin to alternate function */
GPIOB->OTYPER &= ~0x00003000; /* Pin in push-pull mode */
GPIOB->OSPEEDR |= 0x0F000000; /* Slew rate as 100MHz pin */
GPIOB->PUPDR &= ~0x0F000000; /* No pull up, no pull down */
GPIOB->AFR[1] &= ~0x00FF0000;
GPIOB->AFR[1] |= 0x00BB0000; /* Pin to AF11 (Ethernet) */
/* Configure Port B ethernet pins (PB.11) */
GPIOB->MODER &= ~0x00C00000;
GPIOB->MODER |= 0x00800000; /* Pins to alternate function */
GPIOB->OTYPER &= ~0x00000800; /* Pins in push-pull mode */
GPIOB->OSPEEDR |= 0x00C00000; /* Slew rate as 100MHz pin */
GPIOB->PUPDR &= ~0x0FF00000; /* No pull up, no pull down */
GPIOB->AFR[1] &= ~0x0000F000;
GPIOB->AFR[1] |= 0x0000B000; /* Pins to AF11 (Ethernet) */
}
/**********************************************************************************
* global
**********************************************************************************/
/**
* @brief init ehternet controller
*
* @return
*/
BaseType_t xNetworkInterfaceInitialise( void )
{
ETH_InitTypeDef ETH_InitStructure;
/* init randov function */
if( xEMACTaskHandle == NULL )
{
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
RCC->AHB1RSTR |= 0x02000000;
SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII);
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_ETH_MAC | RCC_AHB1Periph_ETH_MAC_Tx | RCC_AHB1Periph_ETH_MAC_Rx | RCC_AHB1Periph_ETH_MAC_PTP, ENABLE);
initEthGpios();
ETH_SoftwareReset();
while (ETH_GetSoftwareResetStatus() == SET);
ETH_StructInit(Ð_InitStructure);
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;
ETH_InitStructure.ETH_ChecksumOffload = ETH_ChecksumOffload_Enable;
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 */
ETH_Init(Ð_InitStructure, PHYAddress);
//Eth_Link_PHYITConfig(0x01);
uint8_t macAdr[] = {0x1E, 0x30, 0x6C, 0xA2, 0x45, 0x5C};
ETH_MACAddressConfig(ETH_MAC_Address0, macAdr);
ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
for(uint32_t i=0; i<ETH_TXBUFNB; i++)
{
ETH_DMATxDescChecksumInsertionConfig(&DMATxDscrTab[i], ETH_DMATxDesc_ChecksumTCPUDPICMPFull);
}
ETH_FlushTransmitFIFO();
ETH_DMATransmissionCmd(ENABLE);
ETH_DMAReceptionCmd(ENABLE);
ETH_MACTransmissionCmd(ENABLE);
ETH_MACReceptionCmd(ENABLE);
/* Reset all interrupts */
ETH->DMASR = 0xFFFFFFFF;
//ETH_DMA_IT_AIS | ETH_DMA_IT_RBU |
ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R, ENABLE);
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = ETH_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x0C;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x0C;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
ETH_Start();
xTaskCreate( prvEMACHandlerTask, "EMAC", configEMAC_TASK_STACK_SIZE, NULL,
configMAX_PRIORITIES - 1, &xEMACTaskHandle );
}
return pdPASS;
}
/**
* @brief output data processing
*
* @param pxDescriptor
* @param bReleaseAfterSend
*
* @return
*/
BaseType_t xNetworkInterfaceOutput( xNetworkBufferDescriptor_t * const pxDescriptor,
BaseType_t bReleaseAfterSend )
{
u32 ulTransmitSize = pxDescriptor->xDataLength;
if( ulTransmitSize > ETH_MAX_PACKET_SIZE )
{
ulTransmitSize = ETH_MAX_PACKET_SIZE;
}
/* Copy bytes to dma buffres */
memcpy( ( void * ) DMATxDscrTab->Buffer1Addr, pxDescriptor->pucEthernetBuffer,
ulTransmitSize );
/* Prepare transmit descriptors to give to DMA. */
ETH_Prepare_Transmit_Descriptors(ulTransmitSize);
iptraceNETWORK_INTERFACE_TRANSMIT();
if( bReleaseAfterSend != pdFALSE )
{
vReleaseNetworkBufferAndDescriptor( pxDescriptor );
}
return pdTRUE;
}
/**
* @brief Ethernet Irq
*/
void ETH_IRQHandler( void )
{
BaseType_t xHigherPriorityTaskWoken = 0;
if (ETH_GetDMAITStatus(ETH_DMA_IT_R) != RESET)
{
ETH_CheckFrameReceived();
ETH_DMAClearITPendingBit(ETH_DMA_IT_R);
vTaskNotifyGiveFromISR( xEMACTaskHandle, &xHigherPriorityTaskWoken );
//portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
}
if (ETH_GetDMAITStatus(ETH_DMA_IT_NIS) != RESET)
{
ETH_DMAClearITPendingBit(ETH_DMA_IT_NIS);
}
if (ETH_GetDMAITStatus(ETH_DMA_IT_AIS) != RESET)
{
ETH_DMAClearITPendingBit(ETH_DMA_IT_AIS);
}
if (ETH_GetDMAITStatus(ETH_DMA_IT_RBU) != RESET)
{
ETH_DMAClearITPendingBit(ETH_DMA_IT_RBU);
}
}
#define BUFFER_SIZE ( ipTOTAL_ETHERNET_FRAME_SIZE + ipBUFFER_PADDING )
#define BUFFER_SIZE_ROUNDED_UP ( ( BUFFER_SIZE + 7 ) & ~0x07UL )
static uint8_t ucBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ][ BUFFER_SIZE_ROUNDED_UP ];
/* Static allocation buffers for FreeRTOS+TCP */
void vNetworkInterfaceAllocateRAMToBuffers(
NetworkBufferDescriptor_t pxNetworkBuffers[ ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS ] )
{
BaseType_t x;
for( x = 0; x < ipconfigNUM_NETWORK_BUFFER_DESCRIPTORS; x++ )
{
pxNetworkBuffers[ x ].pucEthernetBuffer = &( ucBuffers[ x ][ ipBUFFER_PADDING ] );
*( ( uint32_t * ) &ucBuffers[ x ][ 0 ] ) = ( uint32_t ) &( pxNetworkBuffers[ x ] );
}
}
/**
* @brief ethernet driver handling task
*
* @param pvParameters
*/
static void prvEMACHandlerTask( void *pvParameters )
{
NetworkBufferDescriptor_t *pxBufferDescriptor;
size_t xBytesReceived;
IPStackEvent_t xRxEvent;
FrameTypeDef frame;
__IO ETH_DMADESCTypeDef *DMARxNextDesc;
for( ;; )
{
ulTaskNotifyTake( pdFALSE, portMAX_DELAY );
while (ETH_CheckFrameReceived())
{
frame = ETH_Get_Received_Frame();
/* Release descriptors to DMA */
/* Check if frame with multiple DMA buffer segments */
if (DMA_RX_FRAME_infos->Seg_Count > 1)
{
DMARxNextDesc = DMA_RX_FRAME_infos->FS_Rx_Desc;
}
else
{
DMARxNextDesc = frame.descriptor;
}
/* Set Own bit in Rx descriptors: gives the buffers back to DMA */
for (u32 i=0; i<DMA_RX_FRAME_infos->Seg_Count; i++)
{
DMARxNextDesc->Status = ETH_DMARxDesc_OWN;
DMARxNextDesc = (ETH_DMADESCTypeDef *)(DMARxNextDesc->Buffer2NextDescAddr);
}
/* Clear Segment_Count */
DMA_RX_FRAME_infos->Seg_Count =0;
/* When Rx Buffer unavailable flag is set: clear it and resume reception */
if ((ETH->DMASR & ETH_DMASR_RBUS) != (u32)RESET)
{
/* Clear RBUS ETHERNET DMA flag */
ETH->DMASR = ETH_DMASR_RBUS;
/* Resume DMA reception */
ETH->DMARPDR = 0;
}
if ( frame.length > 0 )
{
pxBufferDescriptor = pxGetNetworkBufferWithDescriptor( xBytesReceived, 0 );
if( pxBufferDescriptor != NULL )
{
memcpy( pxBufferDescriptor->pucEthernetBuffer,
( uint8_t * ) frame.buffer, frame.length);
pxBufferDescriptor->xDataLength = frame.length;
if( eConsiderFrameForProcessing( pxBufferDescriptor->pucEthernetBuffer )
== eProcessBuffer )
{
/* The event about to be sent to the TCP/IP is an Rx event. */
xRxEvent.eEventType = eNetworkRxEvent;
/* pvData is used to point to the network buffer descriptor that
now references the received data. */
xRxEvent.pvData = ( void * ) pxBufferDescriptor;
/* Send the data to the TCP/IP stack. */
if( xSendEventStructToIPTask( &xRxEvent, 0 ) == pdFALSE )
{
/* The buffer could not be sent to the IP task so the buffer
must be released. */
vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
/* Make a call to the standard trace macro to log the
occurrence. */
iptraceETHERNET_RX_EVENT_LOST();
}
else
{
/* The message was successfully sent to the TCP/IP stack.
Call the standard trace macro to log the occurrence. */
iptraceNETWORK_INTERFACE_RECEIVE();
}
}
else
{
/* The Ethernet frame can be dropped, but the Ethernet buffer
must be released. */
vReleaseNetworkBufferAndDescriptor( pxBufferDescriptor );
}
}
else
{
/* The event was lost because a network buffer was not available.
Call the standard trace macro to log the occurrence. */
iptraceETHERNET_RX_EVENT_LOST();
}
}
}
}
}
/**********************************************************************************
* eof
**********************************************************************************/
Creating freertos+tcp task
/**
* @file tcpProcess.cpp
* @brief tcp task and etc.
* @author
* @version
* @date 2016-09-16
*/
#include <stdio.h>
/* FreeRTOS includes. */
#include <FreeRTOS.h>
#include "task.h"
#include "timers.h"
#include "queue.h"
#include "semphr.h"
/* FreeRTOS+TCP includes. */
#include "FreeRTOS_IP.h"
#include "FreeRTOS_Sockets.h"
#include "FreeRTOS_DHCP.h"
#include "stm32f4xx.h"
const uint8_t ucIPAddress[ ipIP_ADDRESS_LENGTH_BYTES ] =
{192, 168, 10, 50};
const uint8_t ucNetMask[ ipIP_ADDRESS_LENGTH_BYTES ] =
{ 255, 255, 255, 0 };
const uint8_t ucGatewayAddress[ ipIP_ADDRESS_LENGTH_BYTES ] =
{192, 168, 10, 1};
const uint8_t ucDNSServerAddress[ ipIP_ADDRESS_LENGTH_BYTES ] =
{ 208, 67, 222, 222 };
const uint8_t ucMACAddress[ ipMAC_ADDRESS_LENGTH_BYTES ] =
{ 0x1E, 0x30, 0x6C, 0xA2, 0x45, 0x5C };
/**********************************************************************************
* static
**********************************************************************************/
static void initRandomFunction (void)
{
/* Enable RNG clock source */
RCC_AHB2PeriphClockCmd(RCC_AHB2Periph_RNG, ENABLE);
/* RNG Peripheral enable */
RNG_Cmd(ENABLE);
}
/**********************************************************************************
* global
**********************************************************************************/
/**
* @brief random function
*
* @return
*/
UBaseType_t uxRand( void )
{
const uint32_t ulMultiplier = 0x015a4e35UL, ulIncrement = 1UL;
static BaseType_t xInitialised = pdFALSE;
static UBaseType_t ulNextRand;
/* Don't initialise until the scheduler is running, as the timeout in the
random number generator uses the tick count. */
if( xInitialised == pdFALSE )
{
uint32_t ulSeed;
/* Generate a random number with which to seed the local pseudo random
number generating function. */
while(RNG_GetFlagStatus(RNG_FLAG_DRDY)== RESET);
ulSeed = RNG_GetRandomNumber();
ulNextRand = ulSeed;
xInitialised = pdTRUE;
}
/* Utility function to generate a pseudo random number. */
ulNextRand = ( ulMultiplier * ulNextRand ) + ulIncrement;
return( ( int ) ( ulNextRand >> 16UL ) & 0x7fffUL );
}
/**
* @brief start FreeRTOS+TCP
*/
void initTcpProcess (void)
{
initRandomFunction();
FreeRTOS_IPInit( ucIPAddress, ucNetMask, ucGatewayAddress, ucDNSServerAddress, ucMACAddress );
}
void vApplicationIPNetworkEventHook( eIPCallbackEvent_t eNetworkEvent )
{
}
void vApplicationPingReplyHook( ePingReplyStatus_t eStatus, uint16_t usIdentifier )
{
}
/**********************************************************************************
* eof
**********************************************************************************/