Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Ethrnet на LPC2368 и DP83848I
Форум разработчиков электроники ELECTRONIX.ru > Сайт и форум > В помощь начинающему > Интерфейсы
Lexy_one
Здравствуйте!
Уменя следующая проблема: Ethrnet на LPC2368 и DP83848I не хотит работать. Вернее настроить PHY получилось, проходит автосогласование, определяется скорость и дуплекс, загораются светодиоды Speed, Duplex, даже иногда подмигивает Act, на свитче тоже загораются соответствующие светодиоды, но в процессор не передается ни каких пакетов!
Уже чего только не перепробывал, смотрел примеры и от иара и от кейла. Все вроди сделано правильно!!!? А Пакеты не принимаются (не изменяется индекс производства приема, соответственно и нет принятых данных).
Подскажите уже долго бодаюсь, но ни чего не получается.

Вот код инициализации

Код
void Eth_init(pInt8U MAC)
{
    Int32U Reg,wait;

    PCONP_bit.PCENET = 1;
    POWERDOWN_bit.POWERDOWN = 0;

    PINMODE2    = 0xA02A020A;
    PINSEL2        &= ~(0xF03F030F);
    PINSEL2        |= 0x50150105;
    PINMODE3    = 0x0000000A;
    PINSEL3         &= ~(0x0000000F);
    PINSEL3        |= 0x00000005;

    MAC1 =     MAC1_RES_TX | MAC1_RES_MCS_TX |
                MAC1_RES_RX | MAC1_RES_MCS_RX |
                    MAC1_SIM_RES | MAC1_SOFT_RES;    
    COMMAND = CR_REG_RES | CR_TX_RES | CR_RX_RES;
    MCFG = MCFG_RES_MII;
    for (wait = 100; wait; wait--);
    MAC1 = COMMAND = MCFG = 0;

    MAC1 =     MAC1_PASS_ALL;    
    MAC2 =     MAC2_CRC_EN | MAC2_PAD_EN;

    IPGT = IPGT_HALF_DUP;
    IPGR = IPGR_DEF;
    CLRT = CLRT_DEF;

    MAXF = ETH_MAX_FLEN;
    SUPP = 0;
    TEST = 0;
    MCFG = 0x0018;        // ((CCLK = 48 MHz)/20 = 2,4 MHz)
    MCMD = 0;
    
    COMMAND = CR_PASS_RUNT_FRM | CR_PASS_RX_FILT | CR_RMII;

    SA0 = (((Int16U)MAC[5]) << 8) | ((Int16U)MAC[4]);
    SA1 = (((Int16U)MAC[3]) << 8) | ((Int16U)MAC[2]);
    SA2 = (((Int16U)MAC[1]) << 8) | ((Int16U)MAC[0]);

    for(PhyAddr = 1; PhyAddr < 32; ++PhyAddr)
    {
        // PHY DP83848
        if((PHY_read(PhyAddr, PHY_PHYIDR1) & 0xFFFF) != 0x2000)
            continue;
        if ((PHY_read(PhyAddr, PHY_PHYIDR2) & 0xFFFF) == 0x5C90)
            break;
    }
    if(PhyAddr == 32)    return;

    PHY_write (PhyAddr,PHY_BMCR, BMCR_RESET);
    for (wait = 0; wait < 0x100000; wait++)
    {
        Reg = PHY_read(PhyAddr,PHY_BMCR);
        if(!(Reg & BMCR_RESET)) break;
    }

    Reg = PHY_read_ext(PhyAddr,PHY_RBR);
    if(Reg != (RBR_RMII_MODE | RBR_ELAST_BUFF_2_bit))
        PHY_write_ext(PhyAddr,PHY_RBR, RBR_RMII_MODE | RBR_ELAST_BUFF_2_bit);

    Reg = PHY_read (PhyAddr,PHY_BMSR);
    if(Reg & BMSR_NOPREAM)
        MCFG |= MCFG_SUPP_PREAM;

    Reg = LEDCR_DRV_SODLED | LEDCR_DRV_LNKLED | LEDCR_DRV_ACTLED;
    PHY_write_ext(PhyAddr,PHY_LEDCR, Reg);
    Delay_us(500000);
    Reg = LEDCR_DRV_SODLED | LEDCR_DRV_LNKLED | LEDCR_DRV_ACTLED | LEDCR_SPDLED |
                                LEDCR_LNKLED | LEDCR_ACTLED;
    PHY_write_ext(PhyAddr,PHY_LEDCR, Reg);

    PHY_write_ext(PhyAddr,PHY_MICR, MICR_INTEN | MICR_INT_OE);
    PHY_write_ext(PhyAddr,PHY_MISR, MISR_LINK_INT_EN);

    Eth_descr_init();

    Reg = ANAR_100BT_FULL_D | ANAR_100BT | ANAR_10BT_FULL_D | ANAR_10BT |
                            ANAR_SELECTOR_IEEE_802_3u;
    PHY_write(PhyAddr,PHY_ANAR, Reg);

    PHY_write(PhyAddr,PHY_BMCR, BMCR_AN_EN);

    EthState.AllField = 0;
}


Вот код контроля состояния линии, который крутится в основном цикле

Код
void Eth_Check_State(void)
{
    Int32U Reg;

    Reg = PHY_read_ext (PhyAddr,PHY_PHYSTS);
    if (Reg & PHYSTS_MII_INT)
    {
        if(!EthState.ValidInit)
        {
            if(Reg & PHYSTS_LINK_STS)
            {
                EthState.Link = 1;
                if(Reg & PHYSTS_SPEED_STS)
                {
                    SUPP = SUPP_SPEED_10M;
                    EthState.Speed = 0;
                }
                else
                {
                    SUPP = SUPP_SPEED_100M;
                    EthState.Speed = 1;
                }
                if(Reg & PHYSTS_DUPLEX_STS)
                {
                    MAC2    |= MAC2_FULL_DUP;
                    COMMAND |= CR_FULL_DUP;
                    IPGT     = IPGT_FULL_DUP;
                    EthState.Duplex = 1;
                }
                else
                {
                    MAC2    &= ~(MAC2_FULL_DUP);
                    COMMAND &= ~(CR_FULL_DUP);
                    IPGT     = IPGT_HALF_DUP;
                    EthState.Duplex = 0;
                }
                EthState.ValidInit = 1;

                PHY_write_ext(PhyAddr,PHY_LEDCR, LEDCR_ALL_PHY_DRV);
                
                COMMAND  |= (CR_RX_EN | CR_TX_EN);
                MAC1     |= MAC1_REC_EN;
            }
            else
            {
                MAC1     &= ~(MAC1_REC_EN);
                COMMAND  &= ~(CR_RX_EN | CR_TX_EN);
                EthState.AllField = 0;
                Reg = LEDCR_DRV_SODLED | LEDCR_DRV_LNKLED |
                    LEDCR_DRV_ACTLED | LEDCR_SPDLED |
                        LEDCR_LNKLED | LEDCR_ACTLED;
                PHY_write_ext(PhyAddr,PHY_LEDCR, Reg);
            }
        }
        else
        {
            MAC1     &= ~(MAC1_REC_EN);
            COMMAND  &= ~(CR_RX_EN | CR_TX_EN);
            EthState.AllField = 0;
            Reg = LEDCR_DRV_SODLED | LEDCR_DRV_LNKLED |
                    LEDCR_DRV_ACTLED | LEDCR_SPDLED |
                        LEDCR_LNKLED | LEDCR_ACTLED;
            PHY_write_ext(PhyAddr,PHY_LEDCR, Reg);
            if(Reg & PHYSTS_LINK_STS)
                PHY_write(PhyAddr,PHY_BMCR, BMCR_AN_EN | BMCR_RESTART_AN);
        }
        PHY_read_ext(PhyAddr,PHY_MISR);
    }
    else
    {
        if(Reg & PHYSTS_LINK_STS)
        {
            if(     ((EthState.Speed) && (Reg & PHYSTS_SPEED_STS)) ||
                ((!EthState.Speed) && (!(Reg & PHYSTS_SPEED_STS))) ||
                ((EthState.Duplex) && (!(Reg & PHYSTS_DUPLEX_STS))) ||
                ((!EthState.Duplex) && (Reg & PHYSTS_DUPLEX_STS))    )
            {
                MAC1     &= ~(MAC1_REC_EN);
                COMMAND  &= ~(CR_RX_EN | CR_TX_EN);
                EthState.AllField = 0;
                Reg = LEDCR_DRV_SODLED | LEDCR_DRV_LNKLED |
                        LEDCR_DRV_ACTLED | LEDCR_SPDLED |
                            LEDCR_LNKLED | LEDCR_ACTLED;
                PHY_write_ext(PhyAddr,PHY_LEDCR, Reg);
                if(Reg & PHYSTS_LINK_STS)
                    PHY_write(PhyAddr,PHY_BMCR,
                        BMCR_AN_EN | BMCR_RESTART_AN);
            }
        }
    }
}


Если кто знает в чем проблема, подскажите пожалуста, а то я уже больше недели бодаюсь.
И если код правильный, то может проблема в аппаратке какая то... я ни как не могу разобраться.
PDFки перелапатил и в доль и в поперек, но решения проблемы найти не удалось, а то что предлагают на форуме не помогает!
aaarrr
Цитата(Lexy_one @ Oct 19 2011, 18:40) *
И если код правильный, то может проблема в аппаратке какая то... я ни как не могу разобраться.

Ну, аппаратную проблему как раз проще всего исключить - убедитесь, что при поступлении пакета "снаружи" появляются импульсы на RX[] и RX_DV.
Lexy_one
А линия RX_DV должна заводится на процессор, а то она у меня подтянута резистором к пинанию (для выбора режима RMII ) и на процессор не заводится?
aaarrr
Цитата(Lexy_one @ Oct 19 2011, 19:00) *
А линия RX_DV должна заводится на процессор, а то она у меня подтянута резистором к пинанию (для выбора режима RMII ) и на процессор не заводится?

А как же без нее??? Естественно, процессор ничего не примет.
Lexy_one
Цитата(aaarrr @ Oct 19 2011, 18:06) *
А как же без нее??? Естественно, процессор ничего не примет.

У куда ее надо подключить?

У меня подключены линии:
DP83848 LPC2368
TxEN (2) -> P1.4 (pin 93) (TxEN)
TxD0 (3) -> P1.0 (pin 95) (TxD0)
TxD1 (4) -> P1.1 (pin 94) (TxD1)
RxER (41) -> P1.14 (pin 89) (RxER)
RxD0 (43) -> P1.9 (pin 91) (RxD0)
RxD1 (44) -> P1.10 (pin 90) (RxD1)
CRS (40) -> P1.8 (pin 92) (CRS)
25Mhz (25) -> P1.15 (pin 88) (RxCLK)
MDC (31) -> P1.16 (pin 87) (MDC)
MDIO (30) -> P1.17 (pin 86) (MDIO)

RxDV (39) -> +3,3V (через 2,2кОм)

Все линии Ethernt у процессора заняты.... Так ку даже подключать RX_DV ???
aaarrr
Цитата(Lexy_one @ Oct 19 2011, 19:31) *
Все линии Ethernt у процессора заняты.... Так ку даже подключать RX_DV ???

Пардон, погорячился - есть же CRS_DV еще. Но посмотреть наличие сигналов на них (RXDV и CRS) в любом случае стоит.
Lexy_one
Может есть у кого пример "ПРАВИЛЬНОГО" подключения DP83848I к процессорам LPC23XX, поделитесь или ссылочку дайте... хотелось бы сравнить

Я схему подключения брал вот отсюда

Сигналов на указанных линиях поймать не удалось, хотя линия RX_DV иногда подмигивает, но что это - сигнал или нет - сказать не могу, поскольку мой лучевой осцылограф наверное не в состоянии ловить такие сигналы!
x736C
Согласно DS в интерфейсе RMII сигнал RX_DV не задействован. Достаточно CRS_DV.

На сайте keil'a лежат исходники, с которыми вы сверялись. Там для чтения используется прерывание. А у вас вроде иначе?
Проще будет сначала разобраться с отправкой.

RX_DV пребывает в логической единице на всей длине принимаемого пакета на минимальном интервале ~720 мкс для 100 Мбит/c.

Работал с этим PHY только через ПЛИС -- в этом случае в полном дуплексе вообще можно обойтись без этих сигналов (CRS_DV, DV_RX).
Lexy_one
Цитата(x736C @ Oct 20 2011, 10:44) *
На сайте keil'a лежат исходники, с которыми вы сверялись. Там для чтения используется прерывание. А у вас вроде иначе?


Чтение сделано подобно иаровскому примеру. Я в цикле вычитываю индекс производства приема, и сравниваю его с индексом потребления, откуда вижу что он не изменяется, и делаю вывод, что нет принятых данных.

Цитата(x736C @ Oct 20 2011, 10:44) *
Проще будет сначала разобраться с отправкой.


Мне хотелось бы сначала получить какой либо пакет, для проверки работоспособности устройства. например получить ARP запрос.. или хотябы чтолибо... но я ни чего не получаю... Передачу пакетов я считаю более сложной поскольку с Ethernеt работаю первый раз.

Еще такой вопросик: если происходит нормально автосоглавоние с определением дуплекса и скорости, то можно ли утверждать, что связка PHY --- HUB сделана правильно, и проблема в чемто другом?

Может надо еще чтото настроить для работы кроме Ethernеt, там ДМА например или что либо еще? Я в замешательстве, поскольку ни чего не получается, и начальство в шею гонит, требует результата... И отмазка что горят светодиоды их не устраивает.
x736C
Цитата(Lexy_one @ Oct 20 2011, 12:48) *
Может надо еще чтото настроить для работы кроме Ethernеt, там ДМА например или что либо еще? Я в замешательстве, поскольку ни чего не получается, и начальство в шею гонит, требует результата... И отмазка что горят светодиоды их не устраивает.

Если два PHY смогли договориться между собой, значит на физическом уровне между устройствами порядок.
Скорее всего у Вас ошибка в программе. Но осциллографом надо, конечно, проверить. Установите скорость 10 Мбит/c и проверьте выводы CRS_DV, DV_RX подавая с компа пакеты максимальной длины. Должны увидеть даже на слабеньком осциллографе.

Примеры с Кейла используют DMA, но я не могу конкретнее помочь, потому что, к сожалению, в Си не силен.

Гоните на начальство, у вас веская причина — отсутствует соответствующий осциллограф.
Вам нужно соблюсти временные ограничения чтения пакета через RMII из datasheet.
Остается только программа.

На кейловском сайте есть два-три примера, попробуйте взять один из них в чистом виде, чуть доработать и проверить. Они ориентируются на другой PHY, но RMII должен быть идентичен (проверить в DS).
aaarrr
Цитата(Lexy_one @ Oct 20 2011, 10:53) *
Сигналов на указанных линиях поймать не удалось, хотя линия RX_DV иногда подмигивает, но что это - сигнал или нет - сказать не могу, поскольку мой лучевой осцылограф наверное не в состоянии ловить такие сигналы!


Цитата(Lexy_one @ Oct 20 2011, 12:48) *
Еще такой вопросик: если происходит нормально автосоглавоние с определением дуплекса и скорости, то можно ли утверждать, что связка PHY --- HUB сделана правильно, и проблема в чемто другом?


Если RX_DV "подмигивает" и согласование проходит, то можно с большой долей вероятности утверждать, что железо в порядке.

Цитата(Lexy_one @ Oct 20 2011, 12:48) *
Передачу пакетов я считаю более сложной поскольку с Ethernеt работаю первый раз.

ИМХО, с передачей все как раз значительно проще.
iosifk
Цитата(Lexy_one @ Oct 19 2011, 18:40) *
Здравствуйте!
Уменя следующая проблема: Ethrnet на LPC2368 и DP83848I не хотит работать. Вернее настроить PHY получилось, проходит автосогласование, определяется скорость и дуплекс, загораются светодиоды Speed, Duplex, даже иногда подмигивает Act, на свитче тоже загораются соответствующие светодиоды, но в процессор не передается ни каких пакетов!
...


У меня на сайте есть статья про отладку для KSZ8842. Посмотрите обязательно.
А для Вашего случая я бы делал следующее. Если Вы умеете "настроить PHY " и умеете читать-писать регистры трансивера, то:
1. загоняем команду, устанавливающую цифровую заглушку "сам на себя"... При этом в адресной части должны быть коды широковещательного пакета, который МАС обязан принимать. При этом после передачи пакета МАС обязан (!) сказать Вам, что он принял пакет. Далее считываем пакет и проверяем, что это правильные данные.
2. снимаем цифровую заглушку и ставим в регисты команду сделать аналоговую заглушку. Повторяем. Это скажет нам что на аналоговом входе все ОК!
3. снимаем аналоговую заглушку и в разъем RJ вставляем заглушку из проводков Rx-Tx. Повторяем, убеждаемся, что разъем и трансформатор дело не портят. Смотрим глазковую диаграмму, сравниваем со стандартом...
4. Передаем пакет с тем адресом, который зашит в МАС. Если прием есть, значит МАС понимает адресную часть пакета.

А вот только после этого подключаемся к сети...
Удачи!

Lexy_one
Спасибо за подсказки!
Прием и передачу , с вашей помощью, запустил.

Есть еще пара вопросиков по процессору LPC2368:

1) В пдфке написано, что запускать прием необходимо следующим образом: сначала бит RxEnable в регистре COMMAND, а потом бит RECEIVE_ENABLE в MAC1 (именно в таком порядке). Вопрос в следующем: заперещать прием достаточно ли только в регистре COMMAND, или же еще необходимо запрещать прием в MAC1 (и в каком порядке)?

2) В пдфке написанно что при критической ошибке приема устанавливается бит RxOverrun в регистре IntStatus, по которому эту ошибку можно отловить. А про критическую ошибку передачи написанно только что она возникает, и что надо сбросить канал передачи, а как ее идентифицировать - найти не могу. Вопрос следующий: как идентифицировать фатальную ошибку передачи?
Lexy_one
С вопросом №2 разобрался....
Подскажите пожалуста, кто знает ответ на вопрос №1: Как и в каком порядке запрещать прием?
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.