|
|
  |
STM32F217 & LwIP 1.3.2, Неравномерные отваливающиеся пинги |
|
|
|
Mar 2 2012, 14:22
|

Участник

Группа: Участник
Сообщений: 25
Регистрация: 12-10-11
Из: Москва
Пользователь №: 67 699

|
Имеем плату starterkit STM32F217. Ethernet PHY: KSZ8721BL. С сайта STM взят вот этот пример с реализацией LwIp 1.3.2. Запускаем, начинаем пинговать плату. Все окей, она радостно нам отвечает с пингами <=1мс. Потом в один прекрасный момент, рандомно, пинги начинают съезжать 400-2000мс. В конце концов через несколько часов пинга плата перестает отвечать вообще. При этом весьма забавен тот факт, если с другой машины начинать флудить пингом, то пинги станвятся нормальными 1-40мс. Отключаешь флуд, снова съезжают пинги. Собственно, меняли только настройки драйвера. Изменения отмечены жирным. stm32f2x7_eth_bsp.c CODE #define CHECKSUM_BY_HARDWARE 1
/*...................*/
void ETH_BSP_Config(void) { /* Configure the GPIO ports for ethernet pins */ ETH_GPIO_Config(); /* Config NVIC for Ethernet */ ETH_NVIC_Config();
/* Configure the Ethernet MAC/DMA */ ETH_MACDMA_Config();
/* if (EthInitStatus == 0) { LCD_SetTextColor(Red); LCD_DisplayStringLine(Line5, (uint8_t*)" Ethernet Init "); LCD_DisplayStringLine(Line6, (uint8_t*)" failed "); while(1); }*/
/* Configure the PHY to generate an interrupt on change of link status */ // Eth_Link_PHYITConfig(DP83848_PHY_ADDRESS);
/* Configure the EXTI for Ethernet link status. */ // Eth_Link_EXTIConfig(); }
void ETH_GPIO_Config(void) { GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOs clocks */ RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA | RCC_AHB1Periph_GPIOB | RCC_AHB1Periph_GPIOC | RCC_AHB1Periph_GPIOI | RCC_AHB1Periph_GPIOG | RCC_AHB1Periph_GPIOH | RCC_AHB1Periph_GPIOF, ENABLE);
/* Enable SYSCFG clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE); /* Configure MCO (PA8) */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_8; 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); /* MII/RMII Media interface selection --------------------------------------*/ #ifdef MII_MODE /* Mode MII with STM322xG-EVAL */ #ifdef PHY_CLOCK_MCO
/* Output HSE clock (25MHz) on MCO pin (PA8) to clock the PHY */ RCC_MCO1Config(RCC_MCO1Source_HSE, RCC_MCO1Div_1); #endif /* PHY_CLOCK_MCO */
SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_MII); #elif defined RMII_MODE /* Mode RMII with STM322xG-EVAL *///!
/* Output PLL clock divided by 2 (50MHz) on MCO pin (PA8) to clock the PHY */ RCC_MCO1Config(RCC_MCO1Source_PLLCLK, RCC_MCO1Div_2);
SYSCFG_ETH_MediaInterfaceConfig(SYSCFG_ETH_MediaInterface_RMII); SYSCFG_CompensationCellCmd(ENABLE); #endif /* Configure PA1, PA2 and PA7 */ GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource1, GPIO_AF_ETH);
GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource7, GPIO_AF_ETH);
GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_OD; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_Init(GPIOA, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOA, GPIO_PinSource2, GPIO_AF_ETH);
/* Configure PC1, PC4 and PC5 */ GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOC, GPIO_PinSource4, GPIO_AF_ETH);
GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOC, GPIO_PinSource5, GPIO_AF_ETH);
GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOC, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOC, GPIO_PinSource1, GPIO_AF_ETH);
/* Configure PG14 and PG13 */ GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_100MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOG, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOG, GPIO_PinSource13, GPIO_AF_ETH); GPIO_PinAFConfig(GPIOG, GPIO_PinSource14, GPIO_AF_ETH);
/* Configure PB11 */ GPIO_StructInit(&GPIO_InitStructure); GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_OType = GPIO_OType_PP; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF; GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_Init(GPIOB, &GPIO_InitStructure); GPIO_PinAFConfig(GPIOB, GPIO_PinSource11, GPIO_AF_ETH);
}
system_stm32f2xx.c Код uint32_t SystemCoreClock = 100000000;
Сообщение отредактировал ReRayne - Mar 2 2012, 14:31
|
|
|
|
|
Mar 5 2012, 07:52
|
Участник

Группа: Участник
Сообщений: 24
Регистрация: 20-01-08
Пользователь №: 34 249

|
не все примеры от ST одинаково полезны.
|
|
|
|
|
Mar 5 2012, 11:07
|

Участник

Группа: Участник
Сообщений: 25
Регистрация: 12-10-11
Из: Москва
Пользователь №: 67 699

|
unkier, Lexy_one, да, глюки в самом драйвере к порту LwIP. На форуме STM мне подсказали решение проблемы с пингами: CODE void ethernetif_input(void * pvParameters) { struct pbuf *p;
for( ;; ) { if(xSemaphoreTake(s_xSemaphore, emacBLOCK_TIME_WAITING_FOR_INPUT)==pdTRUE) { GET_NEXT_FRAGMENT: p = low_level_input( s_pxNetIf ); if (p != NULL) { if (ERR_OK != s_pxNetIf->input( p, s_pxNetIf)) { pbuf_free(p); p=NULL; } else { xSemaphoreTake(s_xSemaphore, 0); goto GET_NEXT_FRAGMENT; } } } } }
Но я тут же отловила еще один косяк в static void tcpip_thread(void *arg) в этом куске кода: CODE #if LWIP_ARP if (msg->msg.inp.netif->flags & NETIF_FLAG_ETHARP) { ethernet_input(msg->msg.inp.p, msg->msg.inp.netif); }
Адрес параметра почему-то msg->msg.inp.p = 0x23 => CPU hardfault. После 2Гб пингов.
Сообщение отредактировал ReRayne - Mar 5 2012, 15:40
|
|
|
|
|
Mar 7 2012, 08:22
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(ReRayne @ Mar 7 2012, 12:05)  А ни у кого не пробегал стабильный драйвер для LwIP? Или самой писать? Кстати, для общего развития было бы невредно и написать. У меня простейший драйвер вышел всего на 200 строк. Правда, это для uIP. Но при некоторой сноровке он легко прикручивается к lwip. Ethernet MAC в STM32 порадовал: понятный, разумный, функциональный, значения регистров по умолчанию вменяемые. CODE /** * @file stm32eth.h * @brief Драйвер Ethernet для STM32 */
#include "stm32eth.h" #include "stm32f2regs.h" #include "timer.h" #include "net/uip.h" #include <string.h>
#define SMI_TMPL 0x00000004 /* sets SMI clock range and PHY address */ #define RX_BUF_SIZE 256 #define RX_RING_SIZE 32
static bool link, act; /* the only TX descriptor used in this program */ static uint32_t volatile tx_desc[4] = { 0, 0, (uint32_t)uip_buf, 0 }; static uint32_t volatile rx_desc[RX_RING_SIZE][4]; static uint8_t volatile rx_buf[RX_RING_SIZE][RX_BUF_SIZE]; /* first descriptor in frame, next descriptor to check */ static unsigned int rx_first, rx_cur;
static bool smi_busy(void) { return (ETH_MACMIIAR & 1) != 0; }
static void smi_write(int reg, int val) { ETH_MACMIIDR = val; ETH_MACMIIAR = (reg << 6) | SMI_TMPL | 3; while (smi_busy()) { /* wait */ } }
static void smi_start_read(int reg) { ETH_MACMIIAR = (reg << 6) | SMI_TMPL | 1; }
static int smi_read_data(void) { return ETH_MACMIIDR; }
static void phy_init(void) { smi_write(0, 0x1100); smi_write(4, 0x0021);/* auto-negotiate 10Mb half-duplex only */ }
static void fill_rx_desc(void) { int i; for (i = 0; i < RX_RING_SIZE; i++) { rx_desc[i][0] = (1u << 31); /* OWN bit */ rx_desc[i][1] = RX_BUF_SIZE; rx_desc[i][2] = (uint32_t)&rx_buf[i]; } rx_desc[RX_RING_SIZE - 1][1] |= (1 << 15); /* end of ring */ }
void stm32eth_init(void) { /* enable clocking of MAC core, ports A, B, C */ RCC_AHB1ENR |= 0x1E000007; fill_rx_desc(); GPIOA_AFRL |= 0xB000BBBB; GPIOB_AFRL |= 0x000000BB; GPIOB_AFRH |= 0x00BBBB0B; GPIOC_AFRL |= 0x00BBBBB0; GPIOA_MODER |= 0x000080AA; GPIOB_MODER |= 0x0AA2000A; GPIOC_MODER |= 0x00000AA8; timer_delay(TIMER_TPS / 1000); ETH_DMATDLAR = (uint32_t)&tx_desc; ETH_DMARDLAR = (uint32_t)&rx_desc; ETH_MACCR = (1 << 16) /* disable carrier sense */ | (1 << 3) /* enable transmitter */ | (1 << 2);/* enable receiver */ ETH_DMAOMR = (1 << 21) /* transmit store and forward */ | (1 << 13) /* start transmission */ | (1 << 1);/* start reception */ phy_init(); smi_start_read(1); }
void stm32eth_setmac(const uint8_t mac[6]) { ETH_MACA0LR = *(uint32_t*)mac; ETH_MACA0HR = *(uint16_t*)(mac + 4); }
static void collect_frame(void) { int i, remlen; uint8_t *dst = uip_buf; remlen = (rx_desc[rx_cur & (RX_RING_SIZE - 1)][0] & 0x3FFF0000) >> 16; uip_len = remlen; for (i = rx_first; i <= rx_cur; i++) { int len; len = (i != rx_cur) ? RX_BUF_SIZE : remlen; memcpy(dst, (void*)rx_buf[i & (RX_RING_SIZE - 1)], len); dst += len; remlen -= len; } }
static void reinit_rx_desc(void) { unsigned int i; for (i = rx_cur; i != (rx_first - 1); i--) { rx_desc[i & (RX_RING_SIZE - 1)][0] = 1u << 31; /* OWN bit */ } }
static void rx_poll(void) { uint32_t status; status = rx_desc[rx_cur & (RX_RING_SIZE - 1)][0]; if (status & (1u << 31)) /* OWN bit */ { return; } if (status & (1 << 9)) /* first segment */ { rx_first = rx_cur; } if (status & (1 << 8)) /* last segment */ { if ((status & 0x4000F89F) == 0) /* error bits */ { collect_frame(); } reinit_rx_desc(); } rx_cur++; }
void stm32eth_poll(void) { static timer_value prev; timer_value now; now = timer_getval(); if (timer_ticksbetween(prev, now) > TIMER_TPS / 100) { link = !!(smi_read_data() & 4); smi_start_read(1); prev = now; } rx_poll(); }
void stm32eth_send(void) { tx_desc[1] = uip_len; tx_desc[0] = (1u << 31) /* OWN bit */ | (1 << 29) /* last segment */ | (1 << 28) /* first segment */ | (1 << 21);/* end of ring */ ETH_DMATPDR = 0; /* start transmission */ while (tx_desc[0] & (1u << 31)) { /* wait until TX descriptor is released */ } }
bool stm32eth_link(void) { return link; }
bool stm32eth_act(void) { bool ret; ret = act; act = false; return ret; }
|
|
|
|
|
Mar 9 2012, 13:09
|

Участник

Группа: Участник
Сообщений: 25
Регистрация: 12-10-11
Из: Москва
Пользователь №: 67 699

|
scifi, спасибо!) =F8=, мне такое не подходит, увы, а в доке не могу найти как правильно переинициализировать буфер DMA =( Вообще в low_level_input есть следующий код для переполнения: CODE /* 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; }
Сообщение отредактировал ReRayne - Mar 9 2012, 15:16
|
|
|
|
|
Aug 20 2012, 10:53
|
Участник

Группа: Участник
Сообщений: 24
Регистрация: 20-01-08
Пользователь №: 34 249

|
Цитата(shreck @ Aug 16 2012, 08:23)  Добрый день.
Чем закончилась эта история? Удалось "причесать" драйвер eth и порт lwIP? Может еще какие блохи всплыли в коде?
Интересуюсь потому, что сам недавно начал пытаться запустить эту связку lwIP+ST32F207. Собираю информацию. камень 407. всё отлично.
|
|
|
|
|
Sep 22 2012, 13:29
|
Группа: Новичок
Сообщений: 4
Регистрация: 22-09-12
Пользователь №: 73 641

|
Здесь решили проблемму переполнения буффера при отладке http://lists.gnu.org/archive/html/lwip-use...9/msg00053.htmlЦитата(ReRayne @ Mar 9 2012, 17:09)  scifi, спасибо!) =F8=, мне такое не подходит, увы, а в доке не могу найти как правильно переинициализировать буфер DMA =( Вообще в low_level_input есть следующий код для переполнения: CODE /* 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; }
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|