Skip to content

STM32 EMAC : add configuration choice and connection check #12464

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Mar 3, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,4 @@

#define ETH_IP_VERSION_V1

#define THREAD_STACKSIZE 512

#endif // #define STM32XX_EMAC_CONFIG_H__
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,4 @@

#define ETH_IP_VERSION_V1

#define THREAD_STACKSIZE 512

#endif // #define STM32XX_EMAC_CONFIG_H__
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,4 @@

#define ETH_IP_VERSION_V1

#define THREAD_STACKSIZE 512

#endif // #define STM32XX_EMAC_CONFIG_H__
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,4 @@

#define ETH_IP_VERSION_V2

#define THREAD_STACKSIZE 512

#endif // #define STM32XX_EMAC_CONFIG_H__
36 changes: 34 additions & 2 deletions features/netsocket/emac-drivers/TARGET_STM/mbed_lib.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,41 @@
"config": {
"eth-rxbufnb": 4,
"eth-txbufnb": 4,
"eth-phyaddr": {
"thread-stacksize": {
"help": "Stack size for stm32_emac_thread",
"value": 512
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

how about increasing the value automatically when the trace is enabled? I think for an user it is difficult to guess a valid stacksize when it is configurable.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

During my tests, I didn't see any big difference...

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the adjustable stacksize come in from this:
#12416 (comment)
usually its a system thread and should have a fixed threadsize. Are there other cases than this special with trace enabled where stacksize can be a problem?

},
"eth-phy-address": {
"help" : "Configures actual PHY address according to pullup/down status of PHYAD pin(s)",
"value" : 0
},
"eth-phy-AutoNegotiation": {
"help" : "Selects AutoNegotiation mode : ETH_AUTONEGOTIATION_ENABLE / ETH_AUTONEGOTIATION_DISABLE",
"value" : "ETH_AUTONEGOTIATION_ENABLE"
},
"eth-phy-DuplexMode": {
"help" : "Selects DuplexMode mode : ETH_MODE_FULLDUPLEX / ETH_MODE_HALFDUPLEX",
"value" : "ETH_MODE_FULLDUPLEX"
},
"eth-phy-Speed": {
"help" : "Selects Speed mode : ETH_SPEED_100M / ETH_SPEED_10M",
"value" : "ETH_SPEED_100M"
},
"eth-phy-reset-delay": {
"help" : "Reset process time - Default value: 0.5s as specified in LAN8742A datasheet",
"value" : "500"
},
"eth-phy-status-register": {
"help" : "PHY register Offset with auto-negotiation result - Default value is LAN8742A PHY Special Control/Status Register",
"value" : "31"
},
"eth-phy-speed-status": {
"help" : "Speed mask information in eth-phy-status-register",
"value" : "0x0004"
},
"eth-phy-duplex-status": {
"help" : "Duplex mask information in eth-phy-status-register",
"value" : "0x0010"
}
},
"target_overrides": {
Expand All @@ -14,7 +46,7 @@
"eth-txbufnb": 4
},
"ARCH_MAX": {
"eth-phyaddr": 1
"eth-phy-address": 1
}
}
}
100 changes: 81 additions & 19 deletions features/netsocket/emac-drivers/TARGET_STM/stm32xx_emac.cpp
100755 → 100644
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,22 @@
#include "stm32xx_emac_config.h"
#include "stm32xx_emac.h"

#include "mbed-trace/mbed_trace.h"

#if defined(ETH_IP_VERSION_V2)
#define TRACE_GROUP "STE2"
#else
#define TRACE_GROUP "STE1"
#endif

/* mbed trace feature is supported */
/* ex in mbed_app.json */
/* "mbed-trace.enable": "1" */

/* mbed_trace: debug traces (tr_debug) can be disabled here with no change in mbed_app.json */
// #undef TRACE_LEVEL_DEBUG
// #define TRACE_LEVEL_DEBUG 0

#if defined(ETH_IP_VERSION_V2)
#include "lan8742/lan8742.h"
#include "lwip/memp.h"
Expand All @@ -43,7 +59,6 @@
#define THREAD_PRIORITY (osPriorityHigh)

#define PHY_TASK_PERIOD_MS 200
#define ETH_PHY_ADDRESS MBED_CONF_STM32_EMAC_ETH_PHYADDR

#define STM_HWADDR_SIZE (6)
#define STM_ETH_MTU_SIZE 1500
Expand Down Expand Up @@ -276,13 +291,15 @@ static osThreadId_t create_new_thread(const char *threadName, void (*thread)(voi
bool STM32_EMAC::low_level_init_successful()
#ifndef ETH_IP_VERSION_V2
{
uint32_t PHY_ID;

/* Init ETH */
uint8_t MACAddr[6];
EthHandle.Instance = ETH;
EthHandle.Init.AutoNegotiation = ETH_AUTONEGOTIATION_ENABLE;
EthHandle.Init.Speed = ETH_SPEED_100M;
EthHandle.Init.DuplexMode = ETH_MODE_FULLDUPLEX;
EthHandle.Init.PhyAddress = ETH_PHY_ADDRESS;
EthHandle.Init.AutoNegotiation = MBED_CONF_STM32_EMAC_ETH_PHY_AUTONEGOTIATION;
EthHandle.Init.Speed = MBED_CONF_STM32_EMAC_ETH_PHY_SPEED;
EthHandle.Init.DuplexMode = MBED_CONF_STM32_EMAC_ETH_PHY_DUPLEXMODE;
EthHandle.Init.PhyAddress = MBED_CONF_STM32_EMAC_ETH_PHY_ADDRESS;
#if (MBED_MAC_ADDRESS_SUM != MBED_MAC_ADDR_INTERFACE)
MACAddr[0] = MBED_MAC_ADDR_0;
MACAddr[1] = MBED_MAC_ADDR_1;
Expand All @@ -297,20 +314,48 @@ bool STM32_EMAC::low_level_init_successful()
EthHandle.Init.RxMode = ETH_RXINTERRUPT_MODE;
EthHandle.Init.ChecksumMode = ETH_CHECKSUM_BY_SOFTWARE;
EthHandle.Init.MediaInterface = ETH_MEDIA_INTERFACE_RMII;
HAL_ETH_Init(&EthHandle);
tr_info("PHY Addr %u AutoNegotiation %u", EthHandle.Init.PhyAddress, EthHandle.Init.AutoNegotiation);
tr_debug("MAC Addr %02x:%02x:%02x:%02x:%02x:%02x", MACAddr[0], MACAddr[1], MACAddr[2], MACAddr[3], MACAddr[4], MACAddr[5]);
tr_info("ETH buffers : %u Rx %u Tx", ETH_RXBUFNB, ETH_TXBUFNB);

if (HAL_ETH_Init(&EthHandle) != HAL_OK) {
tr_error("HAL_ETH_Init issue");
return false;
}

uint32_t TempRegisterValue;
if (HAL_ETH_ReadPHYRegister(&EthHandle, 2, &TempRegisterValue) != HAL_OK) {
tr_error("HAL_ETH_ReadPHYRegister 2 issue");
}
PHY_ID = (TempRegisterValue << 16);
if (HAL_ETH_ReadPHYRegister(&EthHandle, 3, &TempRegisterValue) != HAL_OK) {
tr_error("HAL_ETH_ReadPHYRegister 3 issue");
}
PHY_ID |= (TempRegisterValue & 0XFFF0);
tr_info("PHY ID %#X", PHY_ID);

/* Initialize Tx Descriptors list: Chain Mode */
HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB);
if (HAL_ETH_DMATxDescListInit(&EthHandle, DMATxDscrTab, &Tx_Buff[0][0], ETH_TXBUFNB) != HAL_OK) {
tr_error("HAL_ETH_DMATxDescListInit issue");
return false;
}

/* Initialize Rx Descriptors list: Chain Mode */
HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB);
if (HAL_ETH_DMARxDescListInit(&EthHandle, DMARxDscrTab, &Rx_Buff[0][0], ETH_RXBUFNB) != HAL_OK) {
tr_error("HAL_ETH_DMARxDescListInit issue");
return false;
}

/* Configure MAC */
_eth_config_mac(&EthHandle);

/* Enable MAC and DMA transmission and reception */
HAL_ETH_Start(&EthHandle);
if (HAL_ETH_Start(&EthHandle) != HAL_OK) {
tr_error("HAL_ETH_Start issue");
return false;
}

tr_info("low_level_init_successful");
return true;
}
#else // ETH_IP_VERSION_V2
Expand Down Expand Up @@ -338,6 +383,9 @@ bool STM32_EMAC::low_level_init_successful()
EthHandle.Init.TxDesc = DMATxDscrTab;
EthHandle.Init.RxBuffLen = 1524;

tr_debug("MAC Addr %02x:%02x:%02x:%02x:%02x:%02x", MACAddr[0], MACAddr[1], MACAddr[2], MACAddr[3], MACAddr[4], MACAddr[5]);
tr_info("ETH buffers : %u Rx %u Tx", ETH_RX_DESC_CNT, ETH_TX_DESC_CNT);

if (HAL_ETH_Init(&EthHandle) != HAL_OK) {
return false;
}
Expand All @@ -351,6 +399,7 @@ bool STM32_EMAC::low_level_init_successful()
HAL_ETH_DescAssignMemory(&EthHandle, idx, Rx_Buff[idx], NULL);
}

tr_info("low_level_init_successful");
return _phy_init();
}
#endif // ETH_IP_VERSION_V2
Expand All @@ -371,7 +420,7 @@ bool STM32_EMAC::low_level_init_successful()
bool STM32_EMAC::link_out(emac_mem_buf_t *buf)
#ifndef ETH_IP_VERSION_V2
{
bool success;
bool success = true;
emac_mem_buf_t *q;
uint8_t *buffer = reinterpret_cast<uint8_t *>(EthHandle.TxDesc->Buffer1Addr);
__IO ETH_DMADescTypeDef *DmaTxDesc;
Expand Down Expand Up @@ -425,9 +474,10 @@ bool STM32_EMAC::link_out(emac_mem_buf_t *buf)
}

/* Prepare transmit descriptors to give to DMA */
HAL_ETH_TransmitFrame(&EthHandle, framelength);

success = true;
if (HAL_ETH_TransmitFrame(&EthHandle, framelength) != HAL_OK) {
tr_error("HAL_ETH_TransmitFrame issue");
success = false;
}

error:

Expand Down Expand Up @@ -465,7 +515,7 @@ bool STM32_EMAC::link_out(emac_mem_buf_t *buf)
/* copy frame from pbufs to driver buffers */
for (q = p; q != NULL; q = q->next) {
if (i >= ETH_TX_DESC_CNT) {
printf("Error : ETH_TX_DESC_CNT not sufficient\n");
tr_error("Error : ETH_TX_DESC_CNT not sufficient");
goto error;
}

Expand All @@ -491,7 +541,7 @@ bool STM32_EMAC::link_out(emac_mem_buf_t *buf)
if (status == HAL_OK) {
success = 1;
} else {
printf("Error returned by HAL_ETH_Transmit (%d)\n", status);
tr_error("Error returned by HAL_ETH_Transmit (%d)", status);
success = 0;
}

Expand Down Expand Up @@ -530,6 +580,7 @@ int STM32_EMAC::low_level_input(emac_mem_buf_t **buf)

/* get received frame */
if (HAL_ETH_GetReceivedFrame_IT(&EthHandle) != HAL_OK) {
tr_debug("low_level_input no frame");
return -1;
}

Expand All @@ -541,6 +592,7 @@ int STM32_EMAC::low_level_input(emac_mem_buf_t **buf)
dmarxdesc = EthHandle.RxFrameInfos.FSRxDesc;

if (len > 0 && len <= ETH_RX_BUF_SIZE) {
tr_debug("low_level_input len %u", len);
/* Allocate a memory buffer chain from buffer pool */
*buf = memory_manager->alloc_pool(len, 0);
}
Expand Down Expand Up @@ -599,7 +651,7 @@ int STM32_EMAC::low_level_input(emac_mem_buf_t **buf)

if (HAL_ETH_GetRxDataBuffer(&EthHandle, &RxBuff) == HAL_OK) {
if (HAL_ETH_GetRxDataLength(&EthHandle, &frameLength) != HAL_OK) {
printf("Error: returned by HAL_ETH_GetRxDataLength\n");
tr_error("Error: returned by HAL_ETH_GetRxDataLength");
return -1;
}

Expand Down Expand Up @@ -669,14 +721,18 @@ void STM32_EMAC::phy_task()
uint32_t status;

if (HAL_ETH_ReadPHYRegister(&EthHandle, PHY_BSR, &status) == HAL_OK) {
if (emac_link_state_cb) {
if ((emac_link_state_cb) && (status != 0xFFFF)) {
Copy link
Contributor

@JojoS62 JojoS62 Feb 19, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this does not work on my target with LAN8720, still trying to figure out why.

Edit:
fixed, that was a damned wiring error now. Checking against 0xffff works as intended. Wiring error was a fixed level on MDIO pin, and every phy_read returned 0xffff. This is not detected by the interface.

if ((status & PHY_LINKED_STATUS) && !(phy_status & PHY_LINKED_STATUS)) {
tr_info("emac_link_state_cb set to true");
emac_link_state_cb(true);
} else if (!(status & PHY_LINKED_STATUS) && (phy_status & PHY_LINKED_STATUS)) {
tr_info("emac_link_state_cb set to false");
emac_link_state_cb(false);
}
}
phy_status = status;
} else {
tr_error("HAL_ETH_ReadPHYRegister issue");
}

}
Expand Down Expand Up @@ -713,8 +769,10 @@ void STM32_EMAC::phy_task()
if (emac_link_state_cb) {
if (is_up && !was_up) {
emac_link_state_cb(true);
tr_info("emac_link_state_cb set to true");
} else if (!is_up && was_up) {
emac_link_state_cb(false);
tr_info("emac_link_state_cb set to false");
}
}

Expand Down Expand Up @@ -821,6 +879,8 @@ void mbed_default_mac_address(char *mac)

bool STM32_EMAC::power_up()
{
tr_info("power_up");

sleep_manager_lock_deep_sleep();

/* Initialize the hardware */
Expand All @@ -829,13 +889,13 @@ bool STM32_EMAC::power_up()
}

/* Worker thread */
thread = create_new_thread("stm32_emac_thread", &STM32_EMAC::thread_function, this, THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb);
thread = create_new_thread("stm32_emac_thread", &STM32_EMAC::thread_function, this, MBED_CONF_STM32_EMAC_THREAD_STACKSIZE, THREAD_PRIORITY, &thread_cb);

phy_task_handle = mbed::mbed_event_queue()->call_every(PHY_TASK_PERIOD_MS, mbed::callback(this, &STM32_EMAC::phy_task));

#if defined (STM32F767xx) || defined (STM32F769xx) || defined (STM32F777xx)\
|| defined (STM32F779xx)
rmii_watchdog_thread = create_new_thread("stm32_rmii_watchdog", &STM32_EMAC::rmii_watchdog_thread_function, this, THREAD_STACKSIZE, THREAD_PRIORITY, &rmii_watchdog_thread_cb);
rmii_watchdog_thread = create_new_thread("stm32_rmii_watchdog", &STM32_EMAC::rmii_watchdog_thread_function, this, 128, THREAD_PRIORITY, &rmii_watchdog_thread_cb);
#endif

/* Allow the PHY task to detect the initial link state and set up the proper flags */
Expand Down Expand Up @@ -904,6 +964,8 @@ void STM32_EMAC::set_all_multicast(bool all)

void STM32_EMAC::power_down()
{
tr_info("power_down");

/* No-op at this stage */
sleep_manager_unlock_deep_sleep();
}
Expand Down
4 changes: 3 additions & 1 deletion features/netsocket/emac-drivers/TARGET_STM/stm32xx_emac.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
/* Copyright (c) 2017 ARM Limited
* Copyright (c) 2017 STMicroelectronics
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
Expand Down Expand Up @@ -176,4 +178,4 @@ class STM32_EMAC : public EMAC {
int phy_task_handle; /**< Handle for phy task event */
};

#endif /* K64F_EMAC_H_ */
#endif /* STM32_EMAC_H_ */
Loading