Mbed ethernet on STM32

I do not understand is how mbed interfaces with HAL and how I tell mbed which pins to use.
There seems to be a disconnect between the two, where the mbed code seems to work and the HAL code seems to work, but they are not working together.

I can flood the network with data which I receive on my PC using wireshark

for (uint32_t c = 0; c < ETH_TXBUFNB; c++)
      for (int i = 0; i < 1024; i++)
        Tx_Buff[c][i] = c;
HAL_ETH_TransmitFrame(&lan9303.VPHY_Handle, 1024);
  • There is nowhere in my code where I give mbed a reference to ETH_HandleTypeDef
  • There is nowhere in my code where I tell mbed which pins to use

EDIT

I found the class STM32_EMAC I still don’t understand why my own init of the HAL_ETH_Start seems to work (I can write bytes for the network) whereas the mbed implementation STM_EMAC doesn’t seem to do anything using the EthernetInterface class

Mbed ethernet code

   EthernetInterface eth;
   nsapi_error_t ip_err = eth.set_network("192.168.2.50", "255.255.255.0", "192.168.2.254");
   debug("IP status : %d", (int)ip_err);
   nsapi_error_t connect_err = eth.connect();
   debug("Connect status : %d", (int)connect_err);
   debug("IP Address : %s", eth.get_ip_address());
   debug("MAC Address : %s", eth.get_mac_address()); // Doesn't print the MAC address that I used to setup ETH_HandleTypeDef
   TCPSocket sock;
   sock.set_timeout(2000);
   nsapi_error_t sock_open_err = sock.open(&eth);
   debug("Socket open status : %d", (int)sock_open_err);
   nsapi_error_t conn_err = sock.connect("www.arm.com", 80);
   debug("Socket connect status : %d", (int)conn_err);
   char http_cmd[] = "GET / HTTP/1.1\r\nHost: www.arm.com\r\n\r\n";
   int scount = sock.send(http_cmd, sizeof(http_cmd) - 1);
   debug("sent %d [%.*s]", scount, strstr(http_cmd, "\r\n") - http_cmd, http_cmd);
   sock.close();
   eth.disconnect();

HAL ethernet setup

   GPIO_InitTypeDef GPIO_InitStruct = {0};
    __HAL_RCC_ETH_CLK_ENABLE();
    __HAL_RCC_GPIOG_CLK_ENABLE();
    __HAL_RCC_GPIOC_CLK_ENABLE();
    __HAL_RCC_GPIOA_CLK_ENABLE();
    HAL_NVIC_SetPriority(ETH_IRQn, 7, 0);
    HAL_NVIC_EnableIRQ(ETH_IRQn);

    GPIO_InitStruct.Pin = GPIO_PIN_14 | GPIO_PIN_13 | GPIO_PIN_11;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
    HAL_GPIO_Init(GPIOG, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_1 | GPIO_PIN_4 | GPIO_PIN_5;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
    HAL_GPIO_Init(GPIOC, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_1;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_PULLDOWN;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    GPIO_InitStruct.Pin = GPIO_PIN_2 | GPIO_PIN_7;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
    GPIO_InitStruct.Alternate = GPIO_AF11_ETH;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

    VPHY_Handle.Instance = ETH;
    VPHY_Handle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
    VPHY_Handle.Init.Speed = ETH_SPEED_100M;
    VPHY_Handle.Init.PhyAddress = 0;
    VPHY_Handle.Init.MACAddr = &MAC_Address[0];
    VPHY_Handle.Init.RxMode = ETH_RXPOLLING_MODE;
    VPHY_Handle.Init.ChecksumMode = ETH_CHECKSUM_BY_HARDWARE;
    VPHY_Handle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
    VPHY_Handle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;

    PHY_SPECIAL_CONTROL_STATUS vphy_ctl_status;
    vphy_ctl_status.SQE_TEST = true;
    vphy_ctl_status.CLOCK_STRENGTH = true;
    vphy_ctl_status.CLOCK_DIRECTION = true;
    vphy_ctl_status.COLLISION_TEST_PORT = false;
    vphy_ctl_status.TURBO_MII_ENABLE = false;
    vphy_ctl_status.SWITCH_LOOPBACK_PORT = false;
    Write_LAN9303_VPHY_Special_Control_Status_Register(vphy_ctl_status);
    HAL_StatusTypeDef hal_eth_init_status = HAL_ETH_Init(&VPHY_Handle);

    ETH_MACInitTypeDef macconf = {
        .Watchdog = ETH_WATCHDOG_ENABLE,
        .Jabber = ETH_JABBER_ENABLE,
        .InterFrameGap = ETH_INTERFRAMEGAP_96BIT,
        .CarrierSense = ETH_CARRIERSENCE_ENABLE,
        .ReceiveOwn = ETH_RECEIVEOWN_ENABLE,
        .LoopbackMode = ETH_LOOPBACKMODE_DISABLE,
        .ChecksumOffload = ETH_CHECKSUMOFFLAOD_DISABLE,
        .RetryTransmission = ETH_RETRYTRANSMISSION_DISABLE,
        .AutomaticPadCRCStrip = ETH_AUTOMATICPADCRCSTRIP_DISABLE,
        .BackOffLimit = ETH_BACKOFFLIMIT_10,
        .DeferralCheck = ETH_DEFFERRALCHECK_DISABLE,
        .ReceiveAll = ETH_RECEIVEAll_DISABLE,
        .SourceAddrFilter = ETH_SOURCEADDRFILTER_DISABLE,
        .PassControlFrames = ETH_PASSCONTROLFRAMES_BLOCKALL,
        .BroadcastFramesReception = ETH_BROADCASTFRAMESRECEPTION_ENABLE,
        .DestinationAddrFilter = ETH_DESTINATIONADDRFILTER_NORMAL,
        .PromiscuousMode = ETH_PROMISCUOUS_MODE_DISABLE,
        .MulticastFramesFilter = ETH_MULTICASTFRAMESFILTER_NONE, // Disable multicast filter
        .UnicastFramesFilter = ETH_UNICASTFRAMESFILTER_PERFECT,
        .HashTableHigh = 0x0,
        .HashTableLow = 0x0,
        .PauseTime = 0x0,
        .ZeroQuantaPause = ETH_ZEROQUANTAPAUSE_DISABLE,
        .PauseLowThreshold = ETH_PAUSELOWTHRESHOLD_MINUS4,
        .UnicastPauseFrameDetect = ETH_UNICASTPAUSEFRAMEDETECT_DISABLE,
        .ReceiveFlowControl = ETH_RECEIVEFLOWCONTROL_ENABLE,
        .TransmitFlowControl = ETH_TRANSMITFLOWCONTROL_ENABLE,
        .VLANTagComparison = ETH_VLANTAGCOMPARISON_16BIT,
        .VLANTagIdentifier = 0x0};

    HAL_ETH_ConfigMAC(&VPHY_Handle, &macconf);
    ETH_DMADescTypeDef DMATxDscrTab[ETH_TXBUFNB];
    ETH_DMADescTypeDef DMARxDscrTab[ETH_RXBUFNB];

    uint8_t Rx_Buff[ETH_RXBUFNB][ETH_RX_BUF_SIZE];
    uint8_t Tx_Buff[ETH_TXBUFNB][ETH_TX_BUF_SIZE];

    HAL_StatusTypeDef hal_eth_tx_init;
    HAL_StatusTypeDef hal_eth_rx_init;
    HAL_StatusTypeDef hal_eth_start;

    switch (hal_eth_init_status)
    {
    case HAL_OK:
        hal_eth_tx_init = HAL_ETH_DMATxDescListInit(&VPHY_Handle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
        hal_eth_rx_init = HAL_ETH_DMARxDescListInit(&VPHY_Handle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
        hal_eth_start = HAL_ETH_Start(&VPHY_Handle);
        log->debug("ETH init OK (%d) TX init (%d) RX init (%d) start (%d)", hal_eth_init_status, hal_eth_tx_init, hal_eth_rx_init, hal_eth_start);
        break;
    case HAL_ERROR:
        log->debug("ETH init ERROR");
        break;
    case HAL_BUSY:
        log->debug("ETH init BUSY");
        break;
    case HAL_TIMEOUT:
        log->debug("ETH init Timeout");
        break;
    }

Hi Mathieu,

Is this what you are looking for?

It returns STM32_EMAC::get_instance() and that’s how network socket connects to the ethernet driver.

Regards,
Desmond

Thanks for the tip, I did have to write my own EMAC and now its working !