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

для кеил стэка еще системный таймер надо запустить на 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);

 

 

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


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

в Net_Config.h есть такое объявление

extern void init_ethernet (void);

extern void send_frame (OS_FRAME *frame);

 

Это я видел. Самих функций не видел. Как поступить нужно в этой ситуации?

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


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

ну вы их не увидите они в библиотеке кейла вызываются.

у меня тел этих функций тоже нет...

 

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.

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


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

ну вы их не увидите они в библиотеке кейла вызываются.

у меня тел этих функций тоже нет...

 

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.с длжны быть описаны?

 

 

Убедительная просьба - ткните носом в пример от кейла, где все это работает. Попроще пример.

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


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

нет конечно...

то что в хедере есть прототипы функций, совсем не означает что в модуле должно быть их описание. Они в библиотеке, и скрыты от вас как от пользователя.

 

Судя по всем у вас библиотека не подключена, поэтому линкер и не может найти эти функции...

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


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

нет конечно...

то что в хедере есть прототипы функций, совсем не означает что в модуле должно быть их описание. Они в библиотеке, и скрыты от вас как от пользователя.

 

Судя по всем у вас библиотека не подключена, поэтому линкер и не может найти эти функции...

Да подключил, как я понимаю. Или еще как-то нужно?

post-3446-1384282979_thumb.jpg

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


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

БЛИН!

прошу прощения, я вас полностью обманул...

 

вызова этих функций найти нельзя он внутри библиотеки, а сами эти функции должны быть созданы....

 

 

у меня к 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;
}

 

это я чего то реально затупил. Это же привязанные к конкретному железу функции, они не могли быть в библиотеке....

 

у вас должен быть библиотека - драйвер от вашего мак контролера, найдите в ней подходящие функции и организуйте вызов!

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


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

Да подключил, как я понимаю. Или еще как-то нужно?

 

Попробуйте начать с простого.

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. Когда увидите по состоянию регистров физики, что линк поднят - только тогда можно переходить к попыткам поднять стек. Это отдельно уже.

Удачи!

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


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

Что удалось сделать. П.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.

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


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

#include "Net_Config.h"

?

Пробовал. Вылазит куча другого. Думаю для текущего этапа закоментировать - лучшее решение.

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


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

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

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

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

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

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

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

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

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

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