Jump to content
    

Проверить работоспособность Lan8742a

Решил проблему, что-то было не пропаяно.
Кучу раз все проверял, подпаивал, но помогла только основательная пропайка всего (
lan и мк). Какое именно место было проблемное не знаю, так как все сигналы были в норме и визуально тоже проблем не наблюдалось.
В процессе издевался над
nucleo и словил такое же поведение, пропайка так же все решила.
На самом деле мне не понятно почему так получилось, паял нормально, но по-хорошему, видимо, такое надо собирать на линии с автоматической расстановкой и пайкой. Ну или как вариант, плохо отмыл флюс (хотя использовал безотмывочный).
Раз кучу времени потратил на поиск проблем и отладку, опишу, что понял, может кому поможет.

- Пропаиваем все основательно, даже если все выглядит нормально. Отмываем так же. Обязательно безотмывочный флюс.
- Читаем документацию, там много полезного.
- Кварцевый резонатор 25 МГц я ставил DSX530G, но лучше
ABM3. Конденсаторы 27 пФ, но проверял от 12 до 30 пФ, кварц работает. Контролировать можно по 14 пину, при нормальной работе кварца там будет синус 50 МГц почти 4 Вольта, единственный такой сигнал, остальные 3.3В.
- Читаем регистры, положение старшего и младшего битов можно определить по нулевому регистру
BCR, у него первые 8 бит (0-7) зарезервированы нулями. Контролировать можно логическим анализатором (пины MDC и MDIO).
Код чтения регистров:

 

Спойлер
// PHY address
#define LAN8742_PHY_ADDR 						0

//LAN8742 PHY registers
#define LAN8742_BMCR                           0x00
#define LAN8742_BMSR                           0x01
#define LAN8742_PHYID1                         0x02
#define LAN8742_PHYID2                         0x03
#define LAN8742_ANAR                           0x04
#define LAN8742_ANLPAR                         0x05
#define LAN8742_ANER                           0x06
#define LAN8742_ANNPTR                         0x07
#define LAN8742_ANNPRR                         0x08
#define LAN8742_MMDACR                         0x0D
#define LAN8742_MMDAADR                        0x0E
#define LAN8742_ENCTR                          0x10
#define LAN8742_MCSR                           0x11
#define LAN8742_SMR                            0x12
#define LAN8742_TDRPDCR                        0x18
#define LAN8742_TDRCSR                         0x19
#define LAN8742_SECR                           0x1A
#define LAN8742_SCSIR                          0x1B
#define LAN8742_CLR                            0x1C
#define LAN8742_ISR                            0x1D
#define LAN8742_IMR                            0x1E
#define LAN8742_PSCSR                          0x1F

//LAN8742 MMD registers
#define LAN8742_PCS_MMD_DEV_PRES1              0x03, 0x0005
#define LAN8742_PCS_MMD_DEV_PRES2              0x03, 0x0006
#define LAN8742_WUCSR                          0x03, 0x8010
#define LAN8742_WUF_CFGA                       0x03, 0x8011
#define LAN8742_WUF_CFGB                       0x03, 0x8012
#define LAN8742_WUF_MASK                       0x03, 0x8021
#define LAN8742_RX_ADDRA                       0x03, 0x8061
#define LAN8742_RX_ADDRB                       0x03, 0x8062
#define LAN8742_RX_ADDRC                       0x03, 0x8063
#define LAN8742_MCFGR                          0x03, 0x8064
#define LAN8742_VENDOR_SPECIFIC_MMD1_DEV_ID1   0x1E, 0x0002
#define LAN8742_VENDOR_SPECIFIC_MMD1_DEV_ID2   0x1E, 0x0003
#define LAN8742_VENDOR_SPECIFIC_MMD1_DEV_PRES1 0x1E, 0x0005
#define LAN8742_VENDOR_SPECIFIC_MMD1_DEV_PRES2 0x1E, 0x0006
#define LAN8742_VENDOR_SPECIFIC_MMD1_STAT      0x1E, 0x0008
#define LAN8742_TDR_MATCH_THRESHOLD            0x1E, 0x000B
#define LAN8742_TDR_SHORT_OPEN_THRESHOLD       0x1E, 0x000C
#define LAN8742_VENDOR_SPECIFIC_MMD1_PKG_ID1   0x1E, 0x000E
#define LAN8742_VENDOR_SPECIFIC_MMD1_PKG_ID2   0x1E, 0x000F

//Basic Control register
#define LAN8742_BMCR_RESET                     0x8000
#define LAN8742_BMCR_LOOPBACK                  0x4000
#define LAN8742_BMCR_SPEED_SEL                 0x2000
#define LAN8742_BMCR_AN_EN                     0x1000
#define LAN8742_BMCR_POWER_DOWN                0x0800
#define LAN8742_BMCR_ISOLATE                   0x0400
#define LAN8742_BMCR_RESTART_AN                0x0200
#define LAN8742_BMCR_DUPLEX_MODE               0x0100

//Basic Status register
#define LAN8742_BMSR_100BT4                    0x8000
#define LAN8742_BMSR_100BTX_FD                 0x4000
#define LAN8742_BMSR_100BTX_HD                 0x2000
#define LAN8742_BMSR_10BT_FD                   0x1000
#define LAN8742_BMSR_10BT_HD                   0x0800
#define LAN8742_BMSR_100BT2_FD                 0x0400
#define LAN8742_BMSR_100BT2_HD                 0x0200
#define LAN8742_BMSR_EXTENDED_STATUS           0x0100
#define LAN8742_BMSR_AN_COMPLETE               0x0020
#define LAN8742_BMSR_REMOTE_FAULT              0x0010
#define LAN8742_BMSR_AN_CAPABLE                0x0008
#define LAN8742_BMSR_LINK_STATUS               0x0004
#define LAN8742_BMSR_JABBER_DETECT             0x0002
#define LAN8742_BMSR_EXTENDED_CAPABLE          0x0001

//PHY Identifier 1 register
#define LAN8742_PHYID1_PHY_ID_MSB              0xFFFF
#define LAN8742_PHYID1_PHY_ID_MSB_DEFAULT      0x0007

//PHY Identifier 2 register
#define LAN8742_PHYID2_PHY_ID_LSB              0xFC00
#define LAN8742_PHYID2_PHY_ID_LSB_DEFAULT      0xC000
#define LAN8742_PHYID2_MODEL_NUM               0x03F0
#define LAN8742_PHYID2_MODEL_NUM_DEFAULT       0x0130
#define LAN8742_PHYID2_REVISION_NUM            0x000F

//Auto-Negotiation Advertisement register
#define LAN8742_ANAR_NEXT_PAGE                 0x8000
#define LAN8742_ANAR_REMOTE_FAULT              0x2000
#define LAN8742_ANAR_PAUSE                     0x0C00
#define LAN8742_ANAR_100BTX_FD                 0x0100
#define LAN8742_ANAR_100BTX_HD                 0x0080
#define LAN8742_ANAR_10BT_FD                   0x0040
#define LAN8742_ANAR_10BT_HD                   0x0020
#define LAN8742_ANAR_SELECTOR                  0x001F
#define LAN8742_ANAR_SELECTOR_DEFAULT          0x0001

//Auto-Negotiation Link Partner Ability register
#define LAN8742_ANLPAR_NEXT_PAGE               0x8000
#define LAN8742_ANLPAR_ACK                     0x4000
#define LAN8742_ANLPAR_REMOTE_FAULT            0x2000
#define LAN8742_ANLPAR_PAUSE                   0x0400
#define LAN8742_ANLPAR_100BT4                  0x0200
#define LAN8742_ANLPAR_100BTX_FD               0x0100
#define LAN8742_ANLPAR_100BTX_HD               0x0080
#define LAN8742_ANLPAR_10BT_FD                 0x0040
#define LAN8742_ANLPAR_10BT_HD                 0x0020
#define LAN8742_ANLPAR_SELECTOR                0x001F
#define LAN8742_ANLPAR_SELECTOR_DEFAULT        0x0001

//Auto-Negotiation Expansion register
#define LAN8742_ANER_RECEIVE_NP_LOC_ABLE       0x0040
#define LAN8742_ANER_RECEIVE_NP_STOR_LOC       0x0020
#define LAN8742_ANER_PAR_DETECT_FAULT          0x0010
#define LAN8742_ANER_LP_NEXT_PAGE_ABLE         0x0008
#define LAN8742_ANER_NEXT_PAGE_ABLE            0x0004
#define LAN8742_ANER_PAGE_RECEIVED             0x0002
#define LAN8742_ANER_LP_AN_ABLE                0x0001

//Auto Negotiation Next Page TX register
#define LAN8742_ANNPTR_NEXT_PAGE               0x8000
#define LAN8742_ANNPTR_MSG_PAGE                0x2000
#define LAN8742_ANNPTR_ACK2                    0x1000
#define LAN8742_ANNPTR_TOGGLE                  0x0800
#define LAN8742_ANNPTR_MESSAGE                 0x07FF

//Auto Negotiation Next Page RX register
#define LAN8742_ANNPRR_NEXT_PAGE               0x8000
#define LAN8742_ANNPRR_ACK                     0x4000
#define LAN8742_ANNPRR_MSG_PAGE                0x2000
#define LAN8742_ANNPRR_ACK2                    0x1000
#define LAN8742_ANNPRR_TOGGLE                  0x0800
#define LAN8742_ANNPRR_MESSAGE                 0x07FF

//MMD Access Control register
#define LAN8742_MMDACR_FUNC                    0xC000
#define LAN8742_MMDACR_FUNC_ADDR               0x0000
#define LAN8742_MMDACR_FUNC_DATA_NO_POST_INC   0x4000
#define LAN8742_MMDACR_DEVAD                   0x001F

//EDPD NLP/Crossover Time Configuration register
#define LAN8742_ENCTR_EDPD_TX_NLP_EN           0x8000
#define LAN8742_ENCTR_EDPD_TX_NLP_ITS          0x6000
#define LAN8742_ENCTR_EDPD_RX_NLP_WAKE_EN      0x1000
#define LAN8742_ENCTR_EDPD_RX_NLP_MIDS         0x0C00
#define LAN8742_ENCTR_EDPD_EXT_CROSSOVER       0x0002
#define LAN8742_ENCTR_EXT_CROSSOVER_TIME       0x0001

//Mode Control/Status register
#define LAN8742_MCSR_EDPWRDOWN                 0x2000
#define LAN8742_MCSR_FARLOOPBACK               0x0200
#define LAN8742_MCSR_ALTINT                    0x0040
#define LAN8742_MCSR_ENERGYON                  0x0002

//Special Modes register
#define LAN8742_SMR_MODE                       0x00E0
#define LAN8742_SMR_PHYAD                      0x001F

//TDR Patterns/Delay Control register
#define LAN8742_TDRPDCR_DELAY_IN               0x8000
#define LAN8742_TDRPDCR_LINE_BREAK_COUNT       0x7000
#define LAN8742_TDRPDCR_PATTERN_HIGH           0x0FC0
#define LAN8742_TDRPDCR_PATTERN_LOW            0x003F

//TDR Control/Status register
#define LAN8742_TDRCSR_TDR_EN                  0x8000
#define LAN8742_TDRCSR_AD_FILTER_EN            0x4000
#define LAN8742_TDRCSR_CH_CABLE_TYPE           0x0600
#define LAN8742_TDRCSR_CH_STATUS               0x0100
#define LAN8742_TDRCSR_CH_LENGTH               0x00FF

//Symbol Error Counter register
#define LAN8742_SECR_SYM_ERR_CNT               0xFFFF

//Special Control/Status Indication register
#define LAN8742_SCSIR_AMDIXCTRL                0x8000
#define LAN8742_SCSIR_CH_SELECT                0x2000
#define LAN8742_SCSIR_SQEOFF                   0x0800
#define LAN8742_SCSIR_XPOL                     0x0010

//Cable Length register
#define LAN8742_CLR_CBLN                       0xF000

//Interrupt Source Flag register
#define LAN8742_ISR_WOL                        0x0100
#define LAN8742_ISR_ENERGYON                   0x0080
#define LAN8742_ISR_AN_COMPLETE                0x0040
#define LAN8742_ISR_REMOTE_FAULT               0x0020
#define LAN8742_ISR_LINK_DOWN                  0x0010
#define LAN8742_ISR_AN_LP_ACK                  0x0008
#define LAN8742_ISR_PAR_DETECT_FAULT           0x0004
#define LAN8742_ISR_AN_PAGE_RECEIVED           0x0002

//Interrupt Mask register
#define LAN8742_IMR_WOL                        0x0100
#define LAN8742_IMR_ENERGYON                   0x0080
#define LAN8742_IMR_AN_COMPLETE                0x0040
#define LAN8742_IMR_REMOTE_FAULT               0x0020
#define LAN8742_IMR_LINK_DOWN                  0x0010
#define LAN8742_IMR_AN_LP_ACK                  0x0008
#define LAN8742_IMR_PAR_DETECT_FAULT           0x0004
#define LAN8742_IMR_AN_PAGE_RECEIVED           0x0002

//PHY Special Control/Status register
#define LAN8742_PSCSR_AUTODONE                 0x1000
#define LAN8742_PSCSR_HCDSPEED                 0x001C
#define LAN8742_PSCSR_HCDSPEED_10BT_HD         0x0004
#define LAN8742_PSCSR_HCDSPEED_100BTX_HD       0x0008
#define LAN8742_PSCSR_HCDSPEED_10BT_FD         0x0014
#define LAN8742_PSCSR_HCDSPEED_100BTX_FD       0x0018

char binaryStr[17];
uint16_t RegVal = 0;

void int_to_binary(uint16_t num, char *binaryStr)
{
    for(uint8_t i = 0; i < 16; ++i)
    {
        binaryStr[i] = (num % 2) ? '1' : '0';
        num /= 2;
    }
    binaryStr[16] = '\0';
}

void lan8742WritePhyReg(uint8_t address, uint16_t data)
{
	HAL_ETH_WritePHYRegister(&heth, address, data);
}

uint16_t lan8742ReadPhyReg(uint8_t address)
{
   uint16_t data;

   HAL_ETH_ReadPHYRegister(&heth, address, &data);

   return data;
}

uint16_t lan8742ReadMmdReg(uint8_t devAddr, uint16_t regAddr)
{
   lan8742WritePhyReg(LAN8742_MMDACR, LAN8742_MMDACR_FUNC_ADDR | (devAddr & LAN8742_MMDACR_DEVAD));

   lan8742WritePhyReg(LAN8742_MMDAADR, regAddr);

   lan8742WritePhyReg(LAN8742_MMDACR, LAN8742_MMDACR_FUNC_DATA_NO_POST_INC | (devAddr & LAN8742_MMDACR_DEVAD));

   return lan8742ReadPhyReg(LAN8742_MMDAADR);
}

RegVal = lan8742ReadPhyReg(LAN8742_BMCR);
int_to_binary(RegVal, binaryStr);
snprintf(SendStr, 50, "%s\r\n", binaryStr);
HAL_UART_Transmit(&H_USART_DEBUG, (uint8_t*)SendStr, strlen(SendStr), 100);*/

 

Функции чтения взял отсюда: https://www.oryx-embedded.com/doc/lan8742__driver_8c.html
- Режим Loopback: 14й (0-15) бит BCR может активировать режим, при котором все отправленные данные lan8742a сразу же направляет в буфер приема. Я смог его активировать, сделать отправку пакета данных, но принять ничего у меня не получилось. Скорее всего lan резал пакет из-за его заголовка. Причину не знаю, вообще большой минус — это то, что работу PHY я брал из HAL, там найти концы и выдернуть оттуда работу с нижним уровнем сложно. При этом HAL в процессе сам постоянно вмешивается в регистры LAN.
Код отправки фрейма:

Спойлер
#define ETHERNET_HEADER_SIZE 14  // Размер заголовка Ethernet
uint8_t payload[] = "Hello, Ethernet!"; // Данные, которые мы хотим отправить
#define FRAME_LENGTH (ETHERNET_HEADER_SIZE + sizeof(payload)) // Общая длина пакета

uint8_t ethernet_frame[FRAME_LENGTH]; // Буфер для полного Ethernet-кадра

ETH_HandleTypeDef heth;

void prepare_ethernet_frame() {
    // Заполняем Ethernet заголовок
    uint8_t src_mac[6] = {0x00, 0x80, 0xE1, 0x22, 0x33, 0x44};
    uint8_t dest_mac[6] = {0x00, 0x80, 0xE1, 0x11, 0x22, 0x33};

    // Копируем заголовок
    memcpy(ethernet_frame, dest_mac, 6); // Копируем MAC-адрес получателя
    memcpy(ethernet_frame + 6, src_mac, 6); // Копируем MAC-адрес отправителя

    // Устанавливаем тип протокола (например, IPv4)
    ethernet_frame[12] = 0x08; // Тип выше расположенного протокола (для IPv4 0x08 0x00)
    ethernet_frame[13] = 0x00;

    // Копируем полезную нагрузку в кадр
    memcpy(ethernet_frame + ETHERNET_HEADER_SIZE, payload, sizeof(payload));

    // Заполняем буфер данных для передачи
    heth.TxDesc->Buffer1Addr = (uint32_t)ethernet_frame; // Указатель на буфер данных
    heth.TxDesc->ControlBufferSize = (31 & ETH_DMATXDESC_TBS1); // Устанавливаем размер кадра
}

void send_data() {
    prepare_ethernet_frame(); 

    HAL_ETH_TransmitFrame(&heth, FRAME_LENGTH);
}

В цикле с периодичностью вызываем send_data();

 

- Простой TCP сервер

Спойлер
#include "lwip/netif.h"
#include "lwip/ip_addr.h"
#include "lwip/opt.h"
#include "lwip/udp.h"
#include "lwip/ip.h"
#include "lwip/raw.h"
#include "lwip/tcpip.h"
#include "lwip/inet.h"
#include "lwip/pbuf.h"
#include "lwip/timeouts.h"
#include "string.h"
#include <stdint.h>

static struct netconn *conn, *newconn;
static struct netbuf *buf;
static ip_addr_t *addr;
static unsigned short port;
char msg[100];
char smsg[200];

ETH_HandleTypeDef heth;

После инициализации в main или DefaultTask вызываем tcpserver_init();

static void tcp_thread(void *arg)
{
    err_t err, accept_err, recv_error;

    conn = netconn_new(NETCONN_TCP);

    if (conn != NULL)
    {
        err = netconn_bind(conn, IP_ADDR_ANY, 7);

        if (err == ERR_OK)
        {
            netconn_listen(conn);

            while (1)
            {
                accept_err = netconn_accept(conn, &newconn);

                if (accept_err == ERR_OK)
                {
                    // Send a welcome message to the client
                    const char *welcome_msg = "Welcome to the echo server!\n";
                    netconn_write(newconn, welcome_msg, strlen(welcome_msg), NETCONN_COPY);

                    while (netconn_recv(newconn, &buf) == ERR_OK)
                    {
                        addr = netbuf_fromaddr(buf);  // get the address of the client
                        port = netbuf_fromport(buf);  // get the Port of the client

                        do
                        {
                            strncpy(msg, buf->p->payload, buf->p->len);   // get the message from the client

                            // Respond with the received message
                            int len = sprintf(smsg, "\"%s\" was sent by the Server\n", msg);
                            netconn_write(newconn, smsg, len, NETCONN_COPY);  // send the message back to the client
                        }
                        while (netbuf_next(buf) > 0);

                        netbuf_delete(buf);
                    }

                    netconn_close(newconn);
                    netconn_delete(newconn);
                }
            }
        }
        else
        {
            netconn_delete(conn);
        }
    }
}

void tcpserver_init(void)
{
    sys_thread_new("tcp_thread", tcp_thread, NULL, DEFAULT_THREAD_STACKSIZE, osPriorityNormal);
}

 

- Регистр WUCSR тоже полезно прочитать. Там содержатся начальные установки (как писали выше).
Вот значение всех моих регистров последовательно согласно datasheet:

 

Спойлер

0000000010001000
1011010000011110
1110000000000000
1000110010000011
1000011110000000
1000011110110011
1111011000000000
1000000000000100
0000000000000010
0000000000000000
0000000000000000
1000001000000000
0100000000000000
0000011100000110
1011100111011001
0000000000000000
0000000000000000
0101000000000000
0000000000001010
0001001100000000
0000000000000000
0001101000001000
0001000100000000
0000000000000010
0000000000000000
0000000000000000
0000000000000000
0000000000000000
1111111111111111
1111111111111111
1111111111111111
0000000000001000
0000000000000000
0000000000000000
0001000100000000
0000000000000010
0000000000000001
0110001110000000
0101001100000000
0000000000000000
0000000000000000


- Осциллограммы всех пинов приложу ниже (чтобы примерно ориентироваться, что должно быть) + отдельно осциллограммы пинов TXD при отправке фрейма, о котором писал выше.

Вроде все описал, единственное, надо бы все-таки провести линии
TXD и RXD согласно технической документации согласовав по длине и сопротивлению.

 

image.thumb.png.cd26ee4b90dae4de2debeae3543ef84d.pngimage.thumb.png.a21a39fd1619b731492d771057c5d6e1.png

LAN8742_QFN_Rev_A_Routing_Checklist.pdf LAN8742A QFN Rev A Schematic Checklist.pdf

Share this post


Link to post
Share on other sites

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...