Перейти к содержанию
    

Ethernet на STM32F107

Имеется схема на контроллере STM32F107 и свиче KSZ8995, свич подключен к контроллеру по MII и SPI.

 

Что работает: могу обмениваться со свичем информацией по SPI и по MDIO. Со свича идут клоки 25 МГЦ по линиям TX_CLK и RX_CLK, идет информация по линиям RXD0..RXD3, идут стробы по RX_DV. Сам свич "свичует", если подключить Ethernet к портам 1 и 2, можно через такое соединение выходить в интернет, например.

 

Что не работает: хочу микроконтроллером принять пакет от Ethernet на самом нижнем уровне, без всяких TCP/IP, но не могу. Подозреваю, что дело в программе, что-то я настраиваю неправильно (еще и с DMA никогда не работал, а тут без него никак).

Ниже программа, после настроек я в бесконечном цикле проверяю условие (DMARxDscrTab->Status & ETH_DMARxDesc_OWN) == (u32)RESET, но вхожу в это условие только дважды после старта, потом все.

 

______KSZ8995_STM32.pdf

// Процессор STM32F107VCT6
#include "stm32f10x.h"
#include "stm32_eth.h"

#define ETH_RXBUFNB	8 
#define ETH_TXBUFNB	2 

__IO uint32_t HSEStatus = 0;
unsigned char temp = 0;
unsigned int inttemp = 0;
uint32_t uint32temp = 0;

void SetSysClockTo72(void);	// Инициализируем и раздаем клоки
static void SetSysClockTo72(void); 
void InitGPIO(void);		// Инициализируем GPIO
void InitNVIC(void);		// Инициализируем прерывания
void InitTIM(void);		// Инициализируем таймеры
void InitSPI3(void);
void SPI3_WriteByte(unsigned char Data);
unsigned char KSZ8995_ReadByte(unsigned char Address);
void KSZ8995_WriteByte(unsigned char Address, unsigned char Data);

main(void)
{
SetSysClockTo72();			// Инициализируем и раздаем клоки
InitGPIO();				// Инициализируем GPIO
InitNVIC();				// Инициализируем прерывания
InitTIM();				// Инициализируем таймеры
GPIO_PinRemapConfig(GPIO_Remap_SPI3, ENABLE);	// Делаем ремап для работы с SPI3
InitSPI3();

GPIO_SetBits(GPIOD, GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 | GPIO_Pin_11 | GPIO_Pin_12 \
	| GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15);	// Гасим все светодиоды
GPIO_ResetBits(GPIOD, GPIO_Pin_8);	// Зажигаем первый светодиод

GPIO_SetBits(GPIOA, GPIO_Pin_12);	// MDI-X_DISABLE в 1

GPIO_SetBits(GPIOE, GPIO_Pin_2);		// ETH_PWRDN в 1

GPIO_SetBits(GPIOA, GPIO_Pin_4);		// SPI CS

GPIO_SetBits(GPIOE, GPIO_Pin_8);		// Reset KSZ8995 (via ETH_DROP pin)
Delay(2000000);
GPIO_ResetBits(GPIOE, GPIO_Pin_8);
Delay(2000000);
GPIO_SetBits(GPIOE, GPIO_Pin_8);
Delay(12000000);

GPIO_SetBits(GPIOE, GPIO_Pin_4);		// SCONF0
GPIO_ResetBits(GPIOE, GPIO_Pin_3);	// SCONF1
GPIO_ResetBits(GPIOA, GPIO_Pin_5);	// LED5-1

temp = KSZ8995_ReadByte(0x00);
if (temp == 0x95)		// KSZ8995 подключен и исправен
{
	temp = KSZ8995_ReadByte(0x01);
	KSZ8995_WriteByte(0x01, temp|1);
	temp = KSZ8995_ReadByte(0x01);
}

ETH_InitTypeDef ETH_InitStructure;

// Config Ethernet interface as MII, not RMII
GPIO_ETH_MediaInterfaceConfig(GPIO_ETH_MediaInterface_MII);

// Reset ETHERNET on AHB Bus
ETH_DeInit();

// Software reset
ETH_SoftwareReset();

// Wait for software reset 
while(ETH_GetSoftwareResetStatus()==SET);

// Ethernet Configuration
// Call ETH_StructInit if you don't like to configure all ETH_InitStructure parameter
ETH_StructInit(&ETH_InitStructure);

// Fill ETH_InitStructure parametrs
// MAC
ETH_InitStructure.ETH_AutoNegotiation = ETH_AutoNegotiation_Enable;//
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_Enable;//
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_Mode = ETH_Mode_FullDuplex;//
ETH_InitStructure.ETH_Speed = ETH_Speed_100M;//

unsigned int PhyAddr;
for(PhyAddr = 1; 32 >= PhyAddr; PhyAddr++)
{
	if((0x0022 == ETH_ReadPHYRegister(PhyAddr,2))			// PHYID_HIGH
		&& (0x1450 == (ETH_ReadPHYRegister(PhyAddr,3))))	// PHYID_LOW
		break;
}

/* Configure Ethernet */
uint32temp = ETH_Init(&ETH_InitStructure, PhyAddr);

  /* Enable the Ethernet Rx Interrupt */
 ETH_DMAITConfig(ETH_DMA_IT_NIS | ETH_DMA_IT_R, ENABLE);


ETH_DMADESCTypeDef  DMARxDscrTab[ETH_RXBUFNB], DMATxDscrTab[ETH_TXBUFNB];
u8 Rx_Buff[ETH_RXBUFNB][ETH_MAX_PACKET_SIZE], Tx_Buff[ETH_TXBUFNB][ETH_MAX_PACKET_SIZE];

/* Initialize Tx Descriptors list: Chain Mode */
ETH_DMATxDescChainInit(DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
/* Initialize Rx Descriptors list: Chain Mode  */
ETH_DMARxDescChainInit(DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);

DMATxDscrTab->ControlBufferSize = 100;
DMARxDscrTab->ControlBufferSize = ETH_MAX_PACKET_SIZE | (1<<14);
DMARxDscrTab->Status = ETH_DMARxDesc_OWN;

/* Enable MAC and DMA transmission and reception */
ETH_Start();

while(1)
{
	if((DMARxDscrTab->Status & ETH_DMARxDesc_OWN) == (u32)RESET)
	{
		ETH_DMAReceptionCmd(DISABLE);


		temp = Rx_Buff[0][21];

		DMARxDscrTab->Status = ETH_DMARxDesc_OWN;
		ETH_DMAReceptionCmd(ENABLE);
	}

}

}


void InitGPIO(void)	// Инициализируем GPIO
{
GPIO_InitTypeDef GPIO_InitStructure;

// Включаем PA5, 12 на выход (LED51, MDI-X_DISABLE)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_12;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// Включаем PA2 as alternate function push-pull
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);

// Включаем PB5, 8, 11, 12, 13 as alternate function push-pull
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_8 | GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);

// Включаем PC1, 2 as alternate function push-pull
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1 | GPIO_Pin_2;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOC, &GPIO_InitStructure);

// Включаем PD8, 9, 10, 11, 12, 13, 14, 15 на выход (светодиоды)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10 |
	GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_14 | GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);

// Включаем PE2, 3, 4, 8 на выход (ETH_PWRDN, SCONF1, SCONF0, ETH_DROP)
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2 | GPIO_Pin_3 | GPIO_Pin_4 | GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_Init(GPIOE, &GPIO_InitStructure);
}

void InitNVIC(void)		// Инициализируем прерывания
{
/* Set the Vector Table base location at 0x08000000 */
NVIC_SetVectorTable(NVIC_VectTab_FLASH, 0x0);

NVIC_InitTypeDef NVIC_InitStructure;

NVIC_InitStructure.NVIC_IRQChannel = TIM2_IRQn;					// Enable the TIM2 Interrupt
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}

void InitTIM(void)		// Инициализируем таймеры
{
TIM_TimeBaseInitTypeDef		TIM_TimeBaseStructure;

TIM_TimeBaseStructure.TIM_Period = 36000;		// Таймер 0.5 с
TIM_TimeBaseStructure.TIM_Prescaler = 999;
TIM_TimeBaseStructure.TIM_ClockDivision = 0;
TIM_TimeBaseStructure.TIM_CounterMode = TIM_CounterMode_Up;
TIM_TimeBaseInit(TIM2, &TIM_TimeBaseStructure);
TIM_ARRPreloadConfig(TIM2, ENABLE);
TIM_Cmd(TIM2, ENABLE);
TIM_ITConfig(TIM2,TIM_IT_Update,ENABLE);
}

void InitSPI3(void)
{
 GPIO_InitTypeDef  GPIO_InitStructure;
 SPI_InitTypeDef   SPI_InitStructure;

 /* Configure SPI3 pins: SCK and MOSI */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_10 | GPIO_Pin_12;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
 GPIO_Init(GPIOC, &GPIO_InitStructure);

 /* Configure SPI3 pin MISO */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
 GPIO_Init(GPIOC, &GPIO_InitStructure);

 /* Configure PA4 pin: CS pin */
 GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
 GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
 GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
 GPIO_Init(GPIOA, &GPIO_InitStructure);

 /* SPI3 Config */
 SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
 SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
 SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
 SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
 SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
 SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
 SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_128;
 SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
 SPI_InitStructure.SPI_CRCPolynomial = 7;
 SPI_Init(SPI3, &SPI_InitStructure);

 /* SPI3 enable */
 SPI_Cmd(SPI3, ENABLE);
}

unsigned char KSZ8995_ReadByte(unsigned char Address)
{
unsigned char SPI3_Read_Data = 0;

GPIO_ResetBits(GPIOA, GPIO_Pin_4);	// SPI CS

SPI_I2S_SendData(SPI3, 3);				// Send command
while(SPI_I2S_GetFlagStatus(SPI3,SPI_I2S_FLAG_RXNE) != SET);
SPI_I2S_ReceiveData(SPI3);

SPI_I2S_SendData(SPI3, Address);		// Read address
while(SPI_I2S_GetFlagStatus(SPI3,SPI_I2S_FLAG_RXNE) != SET);
SPI_I2S_ReceiveData(SPI3);

SPI_I2S_SendData(SPI3, 0);				// Push foo
while(SPI_I2S_GetFlagStatus(SPI3,SPI_I2S_FLAG_RXNE) != SET);
SPI3_Read_Data = SPI_I2S_ReceiveData(SPI3);

GPIO_SetBits(GPIOA, GPIO_Pin_4);		// SPI CS
//Delay(8000);
return SPI3_Read_Data;
}

void KSZ8995_WriteByte(unsigned char Address, unsigned char Data)
{
GPIO_ResetBits(GPIOA, GPIO_Pin_4);	// SPI CS

SPI_I2S_SendData(SPI3, 2);				// Send command
while(SPI_I2S_GetFlagStatus(SPI3,SPI_I2S_FLAG_RXNE) != SET);
SPI_I2S_ReceiveData(SPI3);

SPI_I2S_SendData(SPI3, Address);		// Send address
while(SPI_I2S_GetFlagStatus(SPI3,SPI_I2S_FLAG_RXNE) != SET);
SPI_I2S_ReceiveData(SPI3);

SPI_I2S_SendData(SPI3, Data);			// Send data
while(SPI_I2S_GetFlagStatus(SPI3,SPI_I2S_FLAG_RXNE) != SET);
SPI_I2S_ReceiveData(SPI3);

GPIO_SetBits(GPIOA, GPIO_Pin_4);		// SPI CS
}

static void SetSysClockTo72(void)
{
 __IO uint32_t StartUpCounter = 0, HSEStatus = 0;

 /* SYSCLK, HCLK, PCLK2 and PCLK1 configuration ---------------------------*/	
 /* Enable HSE */	
 RCC->CR |= ((uint32_t)RCC_CR_HSEON);

 /* Wait till HSE is ready and if Time out is reached exit */
 do
 {
HSEStatus = RCC->CR & RCC_CR_HSERDY;
StartUpCounter++;  
 } while((HSEStatus == 0) && (StartUpCounter != HSEStartUp_TimeOut));

 if ((RCC->CR & RCC_CR_HSERDY) != RESET)
 {
HSEStatus = (uint32_t)0x01;
 }
 else
 {
HSEStatus = (uint32_t)0x00;
 }  

 if (HSEStatus == (uint32_t)0x01)
 {
/* Enable Prefetch Buffer */
FLASH->ACR |= FLASH_ACR_PRFTBE;

/* Flash 2 wait state */
FLASH->ACR &= (uint32_t)((uint32_t)~FLASH_ACR_LATENCY);
FLASH->ACR |= (uint32_t)FLASH_ACR_LATENCY_2;	


/* HCLK = SYSCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_HPRE_DIV1;

/* PCLK2 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE2_DIV1;

/* PCLK1 = HCLK */
RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV2;

#ifdef STM32F10X_CL
/* Configure PLLs ------------------------------------------------------*/
/* PLL2 configuration: PLL2CLK = (HSE / 5) * 8 = 40 MHz */
/* PREDIV1 configuration: PREDIV1CLK = PLL2 / 5 = 8 MHz */

RCC->CFGR2 &= (uint32_t)~(RCC_CFGR2_PREDIV2 | RCC_CFGR2_PLL2MUL |
						  RCC_CFGR2_PREDIV1 | RCC_CFGR2_PREDIV1SRC);
RCC->CFGR2 |= (uint32_t)(RCC_CFGR2_PREDIV2_DIV5 | RCC_CFGR2_PLL2MUL8 |
						 RCC_CFGR2_PREDIV1SRC_PLL2 | RCC_CFGR2_PREDIV1_DIV5);

/* Enable PLL2 */
RCC->CR |= RCC_CR_PLL2ON;
/* Wait till PLL2 is ready */
while((RCC->CR & RCC_CR_PLL2RDY) == 0)
{
}


/* PLL configuration: PLLCLK = PREDIV1 * 9 = 72 MHz */ 
RCC->CFGR &= (uint32_t)~(RCC_CFGR_PLLXTPRE | RCC_CFGR_PLLSRC | RCC_CFGR_PLLMULL);
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLXTPRE_PREDIV1 | RCC_CFGR_PLLSRC_PREDIV1 | 
						RCC_CFGR_PLLMULL9); 
#else	
/*  PLL configuration: PLLCLK = HSE * 9 = 72 MHz */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_PLLSRC | RCC_CFGR_PLLXTPRE |
									RCC_CFGR_PLLMULL));
RCC->CFGR |= (uint32_t)(RCC_CFGR_PLLSRC_HSE | RCC_CFGR_PLLMULL9);
#endif /* STM32F10X_CL */

/* Enable PLL */
RCC->CR |= RCC_CR_PLLON;

/* Wait till PLL is ready */
while((RCC->CR & RCC_CR_PLLRDY) == 0)
{
}

/* Select PLL as system clock source */
RCC->CFGR &= (uint32_t)((uint32_t)~(RCC_CFGR_SW));
RCC->CFGR |= (uint32_t)RCC_CFGR_SW_PLL;	

/* Wait till PLL is used as system clock source */
while ((RCC->CFGR & (uint32_t)RCC_CFGR_SWS) != (uint32_t)0x08)
{
}

// Включаем тактирование GPIOs & AFIO
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC |
RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE| RCC_APB2Periph_AFIO, ENABLE);

// Включаем тактирование таймера 2 и SPI3
RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2 | RCC_APB1Periph_SPI3, ENABLE);

// Включаем тактирование Ethernet
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_ETH_MAC | RCC_AHBPeriph_ETH_MAC_Tx | RCC_AHBPeriph_ETH_MAC_Rx, ENABLE);
 }
 else
 { /* If HSE fails to start-up, the application will have wrong clock 
	 configuration. User can add here some code to deal with this error */	

/* Go to infinite loop */
while (1)
{
}
 }
}

Изменено пользователем IgorKossak
[codebox]

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

как-то удалось решить вопрос? у меня аналогичная проблема, по spi общаюсь, линки между портами 1 и 2 ходят без проблем, могу с процессора выдать сообщение в сеть, но принять ничего не получается.

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

как-то удалось решить вопрос? у меня аналогичная проблема, по spi общаюсь, линки между портами 1 и 2 ходят без проблем, могу с процессора выдать сообщение в сеть, но принять ничего не получается.

Выключите всю фильтрацию в MAC. Скажите ему "пропускать всё".

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

У себя фильтрацию выключил. С другим PHY-драйвером (не коммутатор, а просто один порт Ethernet) все работает без проблем, так что подозреваю, что что-то в KSZ8995 неправильно настроил. Заметил интересную особенность, если опрашивать регистры портов, через которые есть обмен (порт 1 и порт 2), посредством SPI, то в статусных регистрах биты Link Good не установлены. Если опросить регистры MIIM, то в них биты Link Status стоят в 1 (Link is up). Вроде бы противоречие получается

Поделиться сообщением


Ссылка на сообщение
Поделиться на другие сайты

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

×
×
  • Создать...