Author Topic: STM32F429ZI Nucleo Ethernet Problem  (Read 918 times)

0 Members and 1 Guest are viewing this topic.

Offline syntax333Topic starter

  • Regular Contributor
  • *
  • Posts: 158
  • Country: 00
STM32F429ZI Nucleo Ethernet Problem
« on: June 20, 2022, 10:44:23 am »
Hi I am currently working on a project where I have to implement an Ethernet Driver. Below is my code.

Code: [Select]

#include "main.h"

#define ETH_EXTPHY_ADDRESS 0

#define ETH_EXTPHY_BCR 0
#define ETH_EXTPHY_BSR 1
#define ETH_EXTPHY_ANAR 4
#define ETH_EXTPHY_ANLPAR 5
#define ETH_EXTPHY_ANER 6
#define ETH_EXTPHY_PHYSCSR 31

#define ETH_RXBUFNUM 4
#define ETH_TXBUFNUM 2
#define ETH_RXBUFFSIZE 1524
#define ETH_TXBUFFSIZE 1524

uint8_t ETH_TxBuffer[ETH_TXBUFFSIZE];//[ETH_TXBUFNUM][ETH_TXBUFFSIZE];
uint8_t ETH_RxBuffer[ETH_RXBUFNUM][ETH_RXBUFFSIZE];

typedef struct{
uint32_t Status;
uint32_t ControlBufferSize;
uint32_t Buffer1Address;
uint32_t NextDescriptorAddress;
}ETH_Descriptor;

ETH_Descriptor RxDescriptorTable[ETH_RXBUFNUM];
ETH_Descriptor TxDescriptorTable;

void SystemClock_Config(void);

uint16_t ETH_ReadPHYRegister(uint8_t PHYRegAddr)
{
//read data from external PHY register
uint32_t tempReg = 0x0;

while(ETH->MACMIIAR & ETH_MACMIIAR_MB); //Wait until all operations to finish
tempReg |= (ETH_EXTPHY_ADDRESS<<ETH_MACMIIAR_PA_Pos) | (PHYRegAddr<<ETH_MACMIIAR_MR_Pos) | (0b100<<ETH_MACMIIAR_CR_Pos) | ETH_MACMIIAR_MB;
ETH->MACMIIAR = tempReg;

while(ETH->MACMIIAR & ETH_MACMIIAR_MB); //Wait until Data is received
return (ETH->MACMIIDR & 0xFFFF);
}

void ETH_WritePHYRegister(uint8_t PHYRegAddr, uint16_t RegValue)
{
//write data to external PHY register
uint32_t tempReg = 0x0;

while(ETH->MACMIIAR & ETH_MACMIIAR_MB); //Wait until all operations to finish
ETH->MACMIIDR = RegValue; //Load Data to Register
tempReg |= (ETH_EXTPHY_ADDRESS<<ETH_MACMIIAR_PA_Pos) | (PHYRegAddr<<ETH_MACMIIAR_MR_Pos) | (0b100<<ETH_MACMIIAR_CR_Pos) | ETH_MACMIIAR_MW | ETH_MACMIIAR_MB;
ETH->MACMIIAR = tempReg;
}

void Initialization()
{
//----------------GPIO Configuration----------------//
RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN; //Enable Clocks

GPIOA->MODER |= (0b10<<GPIO_MODER_MODE1_Pos) | (0b10<<GPIO_MODER_MODE2_Pos) | (0b10<<GPIO_MODER_MODE7_Pos); //Set Pins as Alternate Function pins
GPIOA->OSPEEDR |= (0b11<<GPIO_OSPEEDR_OSPEED1_Pos) | (0b11<<GPIO_OSPEEDR_OSPEED2_Pos) | (0b11<<GPIO_OSPEEDR_OSPEED7_Pos); //Set Pins as Very High Speed
GPIOA->AFR[0] |= (11<<GPIO_AFRL_AFSEL1_Pos) | (11<<GPIO_AFRL_AFSEL2_Pos) | (11<<GPIO_AFRL_AFSEL7_Pos); //Set pins Alternative Functions

GPIOB->MODER |= (0b10<<GPIO_MODER_MODE11_Pos) | (0b10<<GPIO_MODER_MODE12_Pos) | (0b10<<GPIO_MODER_MODE13_Pos); //Set Pins as Alternate Function pins
GPIOB->OSPEEDR |= (0b11<<GPIO_OSPEEDR_OSPEED11_Pos) | (0b11<<GPIO_OSPEEDR_OSPEED12_Pos) | (0b11<<GPIO_OSPEEDR_OSPEED13_Pos); //Set Pins as Very High Speed
GPIOB->AFR[1] |= (11<<GPIO_AFRH_AFSEL11_Pos) | (11<<GPIO_AFRH_AFSEL12_Pos) | (11<<GPIO_AFRH_AFSEL13_Pos); //Set pins Alternative Functions

GPIOC->MODER |= (0b10<<GPIO_MODER_MODE1_Pos) | (0b10<<GPIO_MODER_MODE4_Pos) | (0b10<<GPIO_MODER_MODE5_Pos); //Set Pins as Alternate Function pins
GPIOC->OSPEEDR |= (0b11<<GPIO_OSPEEDR_OSPEED1_Pos) | (0b11<<GPIO_OSPEEDR_OSPEED4_Pos) | (0b11<<GPIO_OSPEEDR_OSPEED5_Pos); //Set Pins as Very High Speed
GPIOC->AFR[0] |= (11<<GPIO_AFRL_AFSEL1_Pos) | (11<<GPIO_AFRL_AFSEL4_Pos) | (11<<GPIO_AFRL_AFSEL5_Pos); //Set pins Alternative Functions

//----------------SYSCFG Configuration----------------//
RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; //Enable Clocks

SYSCFG->PMC |= SYSCFG_PMC_MII_RMII_SEL; //Select RMII

//----------------Ethernet Configuration----------------//
RCC->AHB1ENR |= RCC_AHB1ENR_ETHMACEN | RCC_AHB1ENR_ETHMACTXEN | RCC_AHB1ENR_ETHMACRXEN; //Enable Clocks

ETH->DMABMR |= ETH_DMABMR_SR; //Resets Ethernet Core
while(ETH->DMABMR & ETH_DMABMR_SR); //Wait until reset completes

//--------PHY Configuration--------//
uint16_t tempRegister;

//Soft Reset PHY
ETH_WritePHYRegister(ETH_EXTPHY_BCR, 0x8000);
while(ETH_ReadPHYRegister(ETH_EXTPHY_BCR) & 0x8000); //Wait until reset completes

//Wait for Linked status
while(!(ETH_ReadPHYRegister(ETH_EXTPHY_BSR) & 0x4)); //Wait until link is up

//Auto negotiation is enabled by hardware.
tempRegister = ETH_ReadPHYRegister(ETH_EXTPHY_BCR);
tempRegister |= (0b1<<9);
ETH_WritePHYRegister(ETH_EXTPHY_BCR, tempRegister); //Restart auto-negotiation.
while(!(ETH_ReadPHYRegister(ETH_EXTPHY_BSR) & (0b1<<5))); //Wait until auto-negotiation completes

//Auto negotiation result
tempRegister = ETH_ReadPHYRegister(ETH_EXTPHY_PHYSCSR);

//--------MAC Configuration--------//
if(((tempRegister>>2) & 0b111) == 0b110) //100BASE-TX Full-duplex
{
ETH->MACCR |= ETH_MACCR_FES | ETH_MACCR_DM;
}
else if(((tempRegister>>2) & 0b111) == 0b010) //100BASE-TX Half-duplex
{
ETH->MACCR |= ETH_MACCR_FES;
}
else if(((tempRegister>>2) & 0b111) == 0b101) //10BASE-T Full-duplex
{
ETH->MACCR |= ETH_MACCR_DM;
}
else  //10BASE-T Half-duplex
{
ETH->MACCR &= ~(ETH_MACCR_FES | ETH_MACCR_DM);
}
ETH->MACCR |= ETH_MACCR_IPCO; //Enable IPv4 Off-load
ETH->MACIMR |= ETH_MACIMR_TSTIM | ETH_MACIMR_PMTIM; //Disable interrupt generation due to time stamp trigger and PMT.

//MAC Address is set here
ETH->MACA0HR &= ~(ETH_MACA0HR_MACA0H); //Clear MAC Address
ETH->MACA0HR |= (0xMACADDRESS<<ETH_MACA0HR_MACA0H_Pos);
ETH->MACA0LR &= ~(ETH_MACA0LR_MACA0L); //Clear MAC Address
ETH->MACA0LR |= (0xMACADDRESS<<ETH_MACA0LR_MACA0L_Pos);

//--------MMC Configuration--------//
//Mask Statistic Interrupts
ETH->MMCRIMR |= ETH_MMCRIMR_RGUFM | ETH_MMCRIMR_RFAEM | ETH_MMCRIMR_RFCEM;
ETH->MMCTIMR |= ETH_MMCTIMR_TGFM | ETH_MMCTIMR_TGFMSCM | ETH_MMCTIMR_TGFSCM;

//--------DMA Configuration--------//

ETH->DMARDLAR = (uint32_t) &RxDescriptorTable[0];
ETH->DMATDLAR = (uint32_t) &TxDescriptorTable;

ETH->DMAOMR |= ETH_DMAOMR_RSF | ETH_DMAOMR_TSF; //Forward Mode

ETH->DMAIER |= ETH_DMAIER_NISE | ETH_DMAIER_RIE; //Enable Rx interrupt

//----------------NVIC Configuration----------------//
NVIC_EnableIRQ(ETH_IRQn);

//--------ETH Start--------//

ETH->MACCR |= ETH_MACCR_TE;
ETH->MACCR |= ETH_MACCR_RE;
ETH->DMAOMR |= ETH_DMAOMR_FTF; // Transmit fifo flush
while(ETH->DMAOMR & ETH_DMAOMR_FTF); // Wait until fifo flushes
ETH->DMAOMR |= ETH_DMAOMR_ST;
ETH->DMAOMR |= ETH_DMAOMR_SR;




}



void ETH_IRQHandler()
{

}

int main(void)
{

  HAL_Init();
  SystemClock_Config();
  Initialization();

  TxDescriptorTable.Status = ETH_DMATXDESC_TCH;
  TxDescriptorTable.ControlBufferSize = 0x0;
  TxDescriptorTable.Buffer1Address = (uint32_t)(&ETH_TxBuffer[0]);
  TxDescriptorTable.NextDescriptorAddress = (uint32_t) &TxDescriptorTable;

  TxDescriptorTable.Status |= ETH_DMATXDESC_CHECKSUMTCPUDPICMPFULL;


  ETH_TxBuffer[0] = 0xff;
  ETH_TxBuffer[1] = 0xff;
  ETH_TxBuffer[2] = 0xff;
  ETH_TxBuffer[3] = 0xff;
  ETH_TxBuffer[4] = 0xff;
  ETH_TxBuffer[5] = 0xff;

  ETH_TxBuffer[6] = 0xMAC1;
  ETH_TxBuffer[7] = 0xMAC2;
  ETH_TxBuffer[8] = 0xMAC3;
  ETH_TxBuffer[9] = 0xMAC4;
  ETH_TxBuffer[10] = 0xMAC5;
  ETH_TxBuffer[11] = 0xMAC6;

  ETH_TxBuffer[12] = 0x08;
  ETH_TxBuffer[13] = 0x06;

  ETH_TxBuffer[14] = 0x00;
  ETH_TxBuffer[15] = 0x01;

  ETH_TxBuffer[16] = 0x08;
  ETH_TxBuffer[17] = 0x00;

  ETH_TxBuffer[18] = 0x06;

  ETH_TxBuffer[19] = 0x04;

  ETH_TxBuffer[20] = 0x00;
  ETH_TxBuffer[21] = 0x01;

  ETH_TxBuffer[22] = 0xMAC1;
  ETH_TxBuffer[23] = 0xMAC2;
  ETH_TxBuffer[24] = 0xMAC3;
  ETH_TxBuffer[25] = 0xMAC4;
  ETH_TxBuffer[26] = 0xMAC5;
  ETH_TxBuffer[27] = 0xMAC6;


  ETH_TxBuffer[28] = 0xc0;
  ETH_TxBuffer[29] = 0xa8;
  ETH_TxBuffer[30] = 0x00;
  ETH_TxBuffer[31] = 0x16;

  ETH_TxBuffer[32] = 0x00;
  ETH_TxBuffer[33] = 0x00;
  ETH_TxBuffer[34] = 0x00;
  ETH_TxBuffer[35] = 0x00;
  ETH_TxBuffer[36] = 0x00;
  ETH_TxBuffer[37] = 0x00;

  ETH_TxBuffer[38] = 0xc0;
  ETH_TxBuffer[39] = 0xa8;
  ETH_TxBuffer[40] = 0x00;
  ETH_TxBuffer[41] = 0x05;



  while(TxDescriptorTable.Status & ETH_DMATXDESC_OWN); //wait until DMA release Descriptor

  TxDescriptorTable.Status |=ETH_DMATXDESC_FS|ETH_DMATXDESC_LS|ETH_DMATXDESC_TER;
  TxDescriptorTable.ControlBufferSize = 42;
  TxDescriptorTable.Status |= ETH_DMATXDESC_OWN;

if (ETH->DMASR & ETH_DMASR_TBUS)
{
ETH->DMASR = ETH_DMASR_TBUS;
ETH->DMATPDR = 0;
}





  while (1)
  {

  }

}


void SystemClock_Config(void)
{
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

  /** Configure the main internal regulator output voltage
  */
  __HAL_RCC_PWR_CLK_ENABLE();
  __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE1);
  /** Initializes the RCC Oscillators according to the specified parameters
  * in the RCC_OscInitTypeDef structure.
  */
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;
  RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
  RCC_OscInitStruct.PLL.PLLM = 8;
  RCC_OscInitStruct.PLL.PLLN = 180;
  RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV2;
  RCC_OscInitStruct.PLL.PLLQ = 4;
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
  {

  }
  /** Activate the Over-Drive mode
  */
  if (HAL_PWREx_EnableOverDrive() != HAL_OK)
  {

  }
  /** Initializes the CPU, AHB and APB buses clocks
  */
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
                              |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV4;
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV2;

  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_5) != HAL_OK)
  {

  }
  SysTick->CTRL &= ~(SysTick_CTRL_ENABLE_Msk);
}





I am trying to send ARP packets to my directly connected laptop without expecting response (Rx is not used). Code runs without MAC controller and DMA controller giving any error. After "ETH->DMATPDR = 0;" Line DMA even releases descriptor to CPU. However, I cannot see any ARP packets with MAC address that I set for STM32 board. I only see laptop ARP packets. I am using wireshark to capture packets in receving end laptop. I can talk with PHY chip without problem.

Since It doesn't give any errors I couldn't figure it out what is wrong.
 

Offline syntax333Topic starter

  • Regular Contributor
  • *
  • Posts: 158
  • Country: 00
Re: STM32F429ZI Nucleo Ethernet Problem
« Reply #1 on: June 20, 2022, 02:12:34 pm »
do anyone have a working example of ETH for stm32 without using LwIP?
 

Offline syntax333Topic starter

  • Regular Contributor
  • *
  • Posts: 158
  • Country: 00
Re: STM32F429ZI Nucleo Ethernet Problem
« Reply #2 on: June 21, 2022, 05:51:00 am »
I have scoped the signals. 25MHz oscillator and 50MHz ref clock is working. However, I measured constant data on Tx+/- Rx+/- pins even though I don't send anything (I am in debug configuration and debug pointer is pointing to at start of the code so it is not running) also both Leds are solid on. Is this behavior normal?
« Last Edit: June 21, 2022, 05:55:35 am by syntax333 »
 

Offline tellurium

  • Regular Contributor
  • *
  • Posts: 229
  • Country: ua
Re: STM32F429ZI Nucleo Ethernet Problem
« Reply #3 on: June 21, 2022, 10:23:09 am »
do anyone have a working example of ETH for stm32 without using LwIP?

Yes - but on nucleo-f746zg. Presumably, the ETH is the same as on 429zi.

Driver: https://github.com/cesanta/mongoose/blob/master/mip/driver_stm32.c
Working reference app: https://github.com/cesanta/mongoose/tree/master/examples/stm32/nucleo-f746zg-baremetal

"MIP" is the name of the (experimental) bare metal stack. Driver interface is simple and is not tied to a specific stack API:
https://github.com/cesanta/mongoose/blob/master/mip/mip.h#L6-L14
You can simply extract that struct definition and stick into your code - and the driver should work.
« Last Edit: June 21, 2022, 10:29:51 am by tellurium »
Open source embedded network library https://mongoose.ws
TCP/IP stack + TLS1.3 + HTTP/WebSocket/MQTT in a single file
 
The following users thanked this post: syntax333


Share me

Digg  Facebook  SlashDot  Delicious  Technorati  Twitter  Google  Yahoo
Smf