war4one 0 22 декабря, 2011 Опубликовано 22 декабря, 2011 (изменено) · Жалоба Имеется схема на контроллере 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(Ð_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(Ð_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) { } } } Изменено 22 декабря, 2011 пользователем IgorKossak [codebox] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
braunevgen 0 16 марта, 2017 Опубликовано 16 марта, 2017 · Жалоба как-то удалось решить вопрос? у меня аналогичная проблема, по spi общаюсь, линки между портами 1 и 2 ходят без проблем, могу с процессора выдать сообщение в сеть, но принять ничего не получается. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
jcxz 172 16 марта, 2017 Опубликовано 16 марта, 2017 · Жалоба как-то удалось решить вопрос? у меня аналогичная проблема, по spi общаюсь, линки между портами 1 и 2 ходят без проблем, могу с процессора выдать сообщение в сеть, но принять ничего не получается. Выключите всю фильтрацию в MAC. Скажите ему "пропускать всё". Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
braunevgen 0 20 марта, 2017 Опубликовано 20 марта, 2017 · Жалоба У себя фильтрацию выключил. С другим PHY-драйвером (не коммутатор, а просто один порт Ethernet) все работает без проблем, так что подозреваю, что что-то в KSZ8995 неправильно настроил. Заметил интересную особенность, если опрашивать регистры портов, через которые есть обмен (порт 1 и порт 2), посредством SPI, то в статусных регистрах биты Link Good не установлены. Если опросить регистры MIIM, то в них биты Link Status стоят в 1 (Link is up). Вроде бы противоречие получается Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться