Golikov 0 11 ноября, 2013 Опубликовано 11 ноября, 2013 · Жалоба для кеил стэка еще системный таймер надо запустить на 1 мСек, чтобы timer_poll(); правильно работал. init_ethernet - это внутренняя функция библиотеки, к LPC есть файл со всеми патрахами мак контроллера в нем написан такой коммент /*---------------------------------------------------------------------------- * EMAC Ethernet Driver Functions *---------------------------------------------------------------------------- * Required functions for Ethernet driver module: * a. Polling mode: - void init_ethernet () * - void send_frame (OS_FRAME *frame) * - void poll_ethernet (void) * b. Interrupt mode: - void init_ethernet () * - void send_frame (OS_FRAME *frame) * - void int_enable_eth () * - void int_disable_eth () * - interrupt function *---------------------------------------------------------------------------*/ в Net_Config.h есть такое объявление extern void init_ethernet (void); extern void send_frame (OS_FRAME *frame); Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
smk 0 12 ноября, 2013 Опубликовано 12 ноября, 2013 · Жалоба в Net_Config.h есть такое объявление extern void init_ethernet (void); extern void send_frame (OS_FRAME *frame); Это я видел. Самих функций не видел. Как поступить нужно в этой ситуации? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 12 ноября, 2013 Опубликовано 12 ноября, 2013 · Жалоба ну вы их не увидите они в библиотеке кейла вызываются. у меня тел этих функций тоже нет... http://www.keil.com/support/man/docs/rlarm...it_ethernet.htm The init_ethernet function is part of RL-TCPnet. The prototype is defined in net_config.h. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
smk 0 12 ноября, 2013 Опубликовано 12 ноября, 2013 · Жалоба ну вы их не увидите они в библиотеке кейла вызываются. у меня тел этих функций тоже нет... http://www.keil.com/support/man/docs/rlarm...it_ethernet.htm The init_ethernet function is part of RL-TCPnet. The prototype is defined in net_config.h. Тогда почему кейл их не видит? Как я понимаю, если в net_config.h они упомянуты, то в net_config.с длжны быть описаны? Убедительная просьба - ткните носом в пример от кейла, где все это работает. Попроще пример. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 12 ноября, 2013 Опубликовано 12 ноября, 2013 · Жалоба нет конечно... то что в хедере есть прототипы функций, совсем не означает что в модуле должно быть их описание. Они в библиотеке, и скрыты от вас как от пользователя. Судя по всем у вас библиотека не подключена, поэтому линкер и не может найти эти функции... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
smk 0 12 ноября, 2013 Опубликовано 12 ноября, 2013 · Жалоба нет конечно... то что в хедере есть прототипы функций, совсем не означает что в модуле должно быть их описание. Они в библиотеке, и скрыты от вас как от пользователя. Судя по всем у вас библиотека не подключена, поэтому линкер и не может найти эти функции... Да подключил, как я понимаю. Или еще как-то нужно? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 13 ноября, 2013 Опубликовано 13 ноября, 2013 · Жалоба БЛИН! прошу прощения, я вас полностью обманул... вызова этих функций найти нельзя он внутри библиотеки, а сами эти функции должны быть созданы.... у меня к LPC есть еще файлик EMAC_LPC17xx.c - там описаны все патроха управления емаком, инициализируются прерывания и мак контроллер в нем есть эта функция void init_ethernet (void) { /* Initialize the EMAC ethernet controller. */ uint32_t regv,tout,id1,id2; DBG_PHY(""); DBG_PHY("\r\nDBG_PHY: Starting Init Physic"); /* Power Up the EMAC controller. */ LPC_SC->PCONP |= 0x40000000; /* Configure PHY */ LPC_GPIO4 -> FIOSET |= 1<<29; LPC_GPIO4 -> FIODIR |= 1<<29; LPC_GPIO1 -> FIOCLR |= 1<<14; LPC_GPIO1 -> FIODIR |= 1<<14; LPC_GPIO1 -> FIOCLR |= 1<<8; LPC_GPIO1 -> FIODIR |= 1<<8; /* Power doun/up Reset PHY for strapping */ LPC_GPIO4 -> FIOCLR |= 1<<29; for(tout=0;tout<1000000;tout++); LPC_GPIO4 -> FIOSET |= 1<<29; for(tout=0;tout<1000000;tout++); /* Enable P1 Ethernet Pins. */ LPC_PINCON->PINSEL2 = 0x50150105; /* LPC176x devices, no MDIO, MDC remap. */ LPC_PINCON->PINSEL3 = (LPC_PINCON->PINSEL3 & ~0x0000000F) | 0x00000005; /* Reset all EMAC internal modules. */ LPC_EMAC->MAC1 = MAC1_RES_TX | MAC1_RES_MCS_TX | MAC1_RES_RX | MAC1_RES_MCS_RX | MAC1_SIM_RES | MAC1_SOFT_RES; LPC_EMAC->Command = CR_REG_RES | CR_TX_RES | CR_RX_RES | CR_PASS_RUNT_FRM; /* A short delay after reset. */ for (tout = 100; tout; tout--); /* Initialize MAC control registers. */ LPC_EMAC->MAC1 = MAC1_PASS_ALL; LPC_EMAC->MAC2 = MAC2_CRC_EN | MAC2_PAD_EN; LPC_EMAC->MAXF = ETH_MAX_FLEN; LPC_EMAC->CLRT = CLRT_DEF; LPC_EMAC->IPGR = IPGR_DEF; /*PCLK=18MHz, clock select=6, MDC=18/6=3MHz */ LPC_EMAC->MCFG = MCFG_CLK_DIV28 | MCFG_RES_MII; for (tout = 100000; tout; tout--); LPC_EMAC->MCFG = MCFG_CLK_DIV28; for (tout = 100000; tout; tout--); /* Enable Reduced MII interface. */ LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM; //LPC_EMAC->Command = CR_RMII | CR_PASS_RUNT_FRM | CR_PASS_RX_FILT; /* Reset Reduced MII Logic. */ LPC_EMAC->SUPP = SUPP_RES_RMII; for (tout = 100; tout; tout--); LPC_EMAC->SUPP = 0; //PHY_ADDR = 0; DBG_PHY("\r\nDBG_PHY: Starting Scan PHY address:\r\n"); //while(1) for(PHY_ADDR = 0; PHY_ADDR<32;PHY_ADDR++) { DBG_PHY("."); /* Put the PHY in reset mode */ write_PHY (PHY_REG_BMCR, 0x8000); for (tout = 10000; tout; tout--); /* Wait for hardware reset to end. */ for (tout = 0; tout < 0x100; tout++) { regv = read_PHY (PHY_REG_BMCR); if (!(regv & 0x8000)) { /* Reset complete */ break; } } if (tout < 0x100) break; else ; //PHY_ADDR++; //PHY_ADDR&=0x1f; } if(PHY_ADDR<31) { DBG_PHY("\r\nDBG_PHY: Found at PHY_ADDR = %d",PHY_ADDR); } else { DBG_PHY_ERR("\r\nDBG_PHY_ERR: PHY_ADDR Error"); return; } /* Check if this is a kz8721 PHY. */ id1 = read_PHY (PHY_REG_IDR1); id2 = read_PHY (PHY_REG_IDR2); DBG_PHY("\r\nDBG_PHY: ID1-0x%04X, ID2-0x%04X",id1, id2); if (((id1 << 16) | (id2 & 0xFFF0)) != 0x221610) { DBG_PHY_ERR("\r\nDDBG_PHY_ERR: Not a KS8721 PHY - ID1-0x%04X, ID2-0x%04X",id1, id2); return; } else { DBG_PHY("\r\nDBG_PHY: KS8721 PHY - Sucñess"); } /* Configure the PHY device */ #if defined (_10MBIT_) /* Connect at 10MBit */ write_PHY (PHY_REG_BMCR, PHY_FULLD_10M); #elif defined (_100MBIT_) /* Connect at 100MBit */ write_PHY (PHY_REG_BMCR, PHY_FULLD_100M); #else DBG_PHY("\r\nDBG_PHY: Starting AutoNegotiation Process\r\n"); /* Use autonegotiation about the link speed. */ write_PHY (PHY_REG_BMCR, PHY_AUTO_NEG); /* Wait to complete Auto_Negotiation. */ for (tout = 0; tout < 0x30000; tout++) { regv = read_PHY (PHY_REG_BMSR); if( !(tout%3000) ) DBG_PHY("."); if (regv & 0x0020) { DBG_PHY("\r\nDBG_PHY: AutoNegotiation Sucñess tout = %d Counts",tout); /* Autonegotiation Complete. */ break; } } #endif if (tout >= 0x30000) { DBG_PHY_ERR("\r\nDBG_PHY_ERR: AutoNegotiation failed."); DBG_PHY_ERR("\r\nDBG_PHY:Possibly Cable Unplugget"); DBG_PHY_ERR("\r\nDBG_PHY:Manual Assign: Full duplex - 100 Mbit Mode"); write_PHY (PHY_REG_BMCR, PHY_FULLD_100M); //return; // auto_neg failed } /* Check the link status. */ for (tout = 0; tout < 0x10000; tout++) { regv = read_PHY (PHY_REG_BMSR); if (regv & 0x0004) { /* Link is on. */ DBG_PHY("\r\nDBG_PHY: Link is ON"); break; } } if (tout >= 0x10000) { DBG_PHY("\r\nDBG_PHY: Link is OFF"); } regv = ((read_PHY (0x1f))>>2)&0x7; /* Configure Full/Half Duplex mode. */ if ((regv==0x0005)||(regv==0x0006)) { /* Full duplex is enabled. */ LPC_EMAC->MAC2 |= MAC2_FULL_DUP; LPC_EMAC->Command |= CR_FULL_DUP; LPC_EMAC->IPGT = IPGT_FULL_DUP; DBG_PHY("\r\nDBG_PHY: Full duplex is enabled."); } if ((regv==0x0001)||(regv==0x0002)) { /* Half duplex mode. */ LPC_EMAC->IPGT = IPGT_HALF_DUP; DBG_PHY("\r\nDBG_PHY: Half duplex is enabled."); } if ((regv==0x0005)||(regv==0x0001)) { /* 10MBit mode. */ LPC_EMAC->SUPP = 0; DBG_PHY("\r\nDBG_PHY: 10MBit mode."); } if ((regv==0x0006)||(regv==0x0002)) { /* 100MBit mode. */ LPC_EMAC->SUPP = SUPP_SPEED; DBG_PHY("\r\nDBG_PHY: 100MBit mode."); } #ifdef DEBUG regv = read_PHY (PHY_REG_BMCR); DBG_PHY("\r\nDBG_PHY: Register 0h - Basic Control = 0x%X",regv); regv = read_PHY (PHY_REG_BMSR); DBG_PHY("\r\nDBG_PHY: Register 1h - Basic Status = 0x%X",regv); regv = read_PHY (PHY_REG_ANAR); DBG_PHY("\r\nDBG_PHY: Register 4h - Auto-Negotiation Advertisement = 0x%X",regv); regv = read_PHY (PHY_REG_ANLPAR); DBG_PHY("\r\nDBG_PHY: Register 5h - Auto-Negotiation Link Partner Ability = 0x%X",regv); regv = read_PHY (PHY_REG_ANER); DBG_PHY("\r\nDBG_PHY: Register 6h - Auto-Negotiation Expansion = 0x%X",regv); regv = read_PHY (PHY_REG_ANNPTR); DBG_PHY("\r\nDBG_PHY: Register 7h - Auto-Negotiation Next Page = 0x%X",regv); regv = read_PHY (PHY_REG_LPNPA); DBG_PHY("\r\nDBG_PHY: Register 8h - Link Partner Next Page Ability = 0x%X",regv); #endif { /* Using Device Serial Number For Define Last 3 MAC Address */ uint32_t p0,p1,p2,p3,s; DBG_PHY("\r\nDBG_PHY: Reading Device Serial Number:"); u32IAP_ReadSerialNumber(&p0, &p1, &p2, &p3); //óïàêóåì ñåðèéíûé íîìåð â 32 áèòà s = p0 + p1 + p2 + p3; //32 áèòà óïàêóåì â 24, ÷òîáû èñïîëüçîâàòü äëÿ ìàê àäðåñà s = s&0xFF + s>>8; DBG_PHY("\r\nDBG_PHY: Chip Serial Number = 0x%08X 0x%08X 0x%08X 0x%08X",p0,p1,p2,p3); DBG_PHY("\r\nDBG_PHY: Chip Summ Serial = 0x%08X ",s); DBG_PHY("\r\nDBG_PHY: Device Hardware Address:" ); own_hw_adr[3] = ( (s>>16) & 0xFF); own_hw_adr[4] = ( (s>>8 ) & 0xFF); own_hw_adr[5] = ( (s ) & 0xFF); DBG_PHY("\r\nDBG_PHY: %02X %02X %02X %02X %02X %02X", own_hw_adr[0], own_hw_adr[1], own_hw_adr[2], own_hw_adr[3], own_hw_adr[4], own_hw_adr[5] ); } /* Set the Ethernet MAC Address registers */ LPC_EMAC->SA0 = ((uint32_t)own_hw_adr[5] << 8) | (uint32_t)own_hw_adr[4]; LPC_EMAC->SA1 = ((uint32_t)own_hw_adr[3] << 8) | (uint32_t)own_hw_adr[2]; LPC_EMAC->SA2 = ((uint32_t)own_hw_adr[1] << 8) | (uint32_t)own_hw_adr[0]; /* Initialize Tx and Rx DMA Descriptors */ rx_descr_init (); tx_descr_init (); /* Receive Broadcast, Multicast and Perfect Match Packets */ LPC_EMAC->RxFilterCtrl = RFC_MCAST_EN | RFC_BCAST_EN | RFC_PERFECT_EN; /* Receive Broadcast and Perfect Match Packets */ //LPC_EMAC->RxFilterCtrl = RFC_BCAST_EN | RFC_PERFECT_EN; /* Enable EMAC interrupts. */ LPC_EMAC->IntEnable = INT_RX_DONE | INT_TX_DONE ; /* Reset all interrupts */ LPC_EMAC->IntClear = 0xFFFF; /* Enable receive and transmit mode of MAC Ethernet core */ LPC_EMAC->Command |= (CR_RX_EN | CR_TX_EN); LPC_EMAC->MAC1 |= MAC1_REC_EN; DBG_PHY("\r\nDBG_PHY: PHY Config Done\r\n" ); return; } посылка фрейма там же void send_frame (OS_FRAME *frame) { /* Send frame to EMAC ethernet controller */ uint32_t idx,len; uint32_t *sp,*dp; idx = LPC_EMAC->TxProduceIndex; sp = (uint32_t *)&frame->data[0]; dp = (uint32_t *)Tx_Desc[idx].Packet; /* Copy frame data to EMAC packet buffers. */ for (len = (frame->length + 3) >> 2; len; len--) { *dp++ = *sp++; } Tx_Desc[idx].Ctrl = (frame->length-1) | (TCTRL_INT | TCTRL_LAST); /* Start frame transmission. */ if (++idx == NUM_TX_FRAG) idx = 0; LPC_EMAC->TxProduceIndex = idx; } это я чего то реально затупил. Это же привязанные к конкретному железу функции, они не могли быть в библиотеке.... у вас должен быть библиотека - драйвер от вашего мак контролера, найдите в ней подходящие функции и организуйте вызов! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ksv198 0 13 ноября, 2013 Опубликовано 13 ноября, 2013 · Жалоба Да подключил, как я понимаю. Или еще как-то нужно? Попробуйте начать с простого. 1. Создайте пустой проект в Кейле, где есть только начальная инициализация STM32F107 и убедитесь, что контроллер нормально запускается (например мигает светодиодом). Хорошо бы проконтролировать частоту ядра выводом на выход PA8. 2. Далее подключите в проект файлы ETH_STM32X.c и ETH_STM32X.h (лежат в c:\Keil\ARM\RL\TCPnet\Drivers\). Это драйвер Кейла для Ethernet MAC и инициализация PHY. Он очень простой по сравнению с STM-овским, в нём легче разобраться для начала. По умолчанию там всё для физики DP83848C. 3. Вам нужно поправить в ETH_STM32X.h всё, что ниже строки комментария /* DP83848C PHY Registers */. Для простоты я бы оставил сначала только первые 8 регистров, для проверки работоспособности хватит (если у Вас RTL8201 то первые 6 регистров). Исправьте #define DP83848C_ID 0x20005C90 на свой (из даташита на Вашу микросхему физики). Исправьте #define DP83848C_DEF_ADR 0x01 на адрес Вашей микросхемы физики (обратите внимание, что он может изменяться от схемы включения - всё описано в даташите). 4. Далее в файле ETH_STM32X.c идём в функцию void init_ethernet (void). Там два варианта подключения физики - по MII или по RMII. Оставьте только свой вариант, чтобы не путаться. Затем необходимо обратить внимание на строку /* MDC Clock range 60-72MHz. */ ETH->MACMIIAR = 0x00000000; Если у Вас частота ядра менее 60 МГц, то надо из референс мануал подставить другое значение (см. RM0008 раздел SMI clock selection). Уберите временно проверку по условию if (((id1 << 16) | (id2 & 0xFFF0)) == DP83848C_ID) - это проверка идентификатора физики. Уберите блок от /* Check the link status. */ - в Вашей микросхеме физики может не быть этого регистра. Обратите внимание на массив extern U8 own_hw_adr[];. Это массив МАС адреса, на данном этапе, чтобы не подключать Net_Config.c определите его локально (не забудьте младший байт поставить в 0х00 для начала, чтобы случайно не сделать броадкаст). 5. Начинаем отладку. В main() вызываем init_ethernet () и Вашим любимым методом (дебагом или принтом через последовательный порт, или выводом на экранчик, если есть) смотрим возвращаемые функцией read_PHY() значения. Сравнивайте с тем, что видите в описании битов регистра в даташите на Ваш PHY. Здесь пригодятся регистры 0х02 и 0х03 - в них идентификатор. Если все время читается 0xff или 0х00 то попробуйте менять адрес (в строке #define DP83848C_DEF_ADR) от 0 до 32. Если все равно ничего не получается возвращайтесь к анализу схемы (желательно с осциллографом). 6. Когда начнут нормально читаться регистры, пройдитесь по всем доступным в даташите и посмотрите, что с физикой становится после инициализации. Возможно будут проблемы с autonegotiation - PHY может не определить скорость сам. Пните его принудительно: write_PHY (PHY_REG_BMCR, PHY_FULLD_10M); или write_PHY (PHY_REG_BMCR, PHY_FULLD_100M);. 7. Когда увидите по состоянию регистров физики, что линк поднят - только тогда можно переходить к попыткам поднять стек. Это отдельно уже. Удачи! Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
smk 0 13 ноября, 2013 Опубликовано 13 ноября, 2013 · Жалоба ksv198, благодарю! как глоток воздуха! Сделаю - отпишусь. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DmitryM 0 13 ноября, 2013 Опубликовано 13 ноября, 2013 · Жалоба менять адрес (в строке #define DP83848C_DEF_ADR) от 0 до 32. от 0 до 31 Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
ksv198 0 13 ноября, 2013 Опубликовано 13 ноября, 2013 · Жалоба от 0 до 31 Вы правы Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
smk 0 13 ноября, 2013 Опубликовано 13 ноября, 2013 · Жалоба Что удалось сделать. П.1-4 сделал полностью. Инициализацию пинов сделал без ремапа так, как собрано на плате. Добавил #include "type.h" чтоб вручную все не доводить. Но дальше не пошло т.к. остались сообщения об ошибке: ETH_keil.axf: Error: L6218E: Undefined symbol alloc_mem (referred from eth_stm32x.o). ETH_keil.axf: Error: L6218E: Undefined symbol put_in_queue (referred from eth_stm32x.o). Что можно предпринять? Спасибо. Вот там похоже упомянуты: /*--------------------------- interrupt_ethernet ----------------------------*/ void ETH_IRQHandler (void) { /* Ethernet Controller Interrupt function. */ OS_FRAME *frame; U32 i,RxLen,int_stat; U32 *sp,*dp; while (((int_stat = ETH->DMASR) & INT_NISE) != 0) { ETH->DMASR = int_stat; if (int_stat & INT_RIE) { /* Valid frame has been received. */ i = RxBufIndex; if (Rx_Desc[i].Stat & DMA_RX_ERROR_MASK) { goto rel; } if ((Rx_Desc[i].Stat & DMA_RX_SEG_MASK) != DMA_RX_SEG_MASK) { goto rel; } RxLen = ((Rx_Desc[i].Stat >> 16) & 0x3FFF) - 4; if (RxLen > ETH_MTU) { /* Packet too big, ignore it and free buffer. */ goto rel; } /* Flag 0x80000000 to skip sys_error() call when out of memory. */ frame = alloc_mem (RxLen | 0x80000000); /* if 'alloc_mem()' has failed, ignore this packet. */ if (frame != NULL) { sp = (U32 *)(Rx_Desc[i].Addr & ~3); dp = (U32 *)&frame->data[0]; for (RxLen = (RxLen + 3) >> 2; RxLen; RxLen--) { *dp++ = *sp++; } put_in_queue (frame); } /* Release this frame from ETH IO buffer. */ rel: Rx_Desc[i].Stat = DMA_RX_OWN; if (++i == NUM_RX_BUF) i = 0; RxBufIndex = i; } if (int_stat & INT_TIE) { /* Frame transmit completed. */ } } } Закоментировал обработчик и получилось скомпилировать. Физику читает, идентификатор читает правильно. Линк светится. С autonegotiation проблем нет если кабель подключен. PHY_REG_BMSR = 0x7869. Адрес физики = 31. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 13 ноября, 2013 Опубликовано 13 ноября, 2013 · Жалоба #include "Net_Config.h" ? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
smk 0 13 ноября, 2013 Опубликовано 13 ноября, 2013 · Жалоба #include "Net_Config.h" ? Пробовал. Вылазит куча другого. Думаю для текущего этапа закоментировать - лучшее решение. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
Golikov 0 13 ноября, 2013 Опубликовано 13 ноября, 2013 · Жалоба ну тогда остается только свои функции - заглушки написать. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться