andysworkshop / stm32plus

The C++ library for the STM32 F0, F100, F103, F107 and F4 microcontrollers

Home Page:http://www.andybrown.me.uk

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

LAN8710A network stack oddity.

mikeodr opened this issue · comments

I'm running into a strange issue with the network stack for the LAN8710A when initialised as the following:

  typedef stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A> PhysicalLayer;
  typedef stm32plus::net::DatalinkLayer <
  PhysicalLayer,
  stm32plus::net::DefaultRmiiInterface,
  stm32plus::net::Mac > DatalinkLayer;
  typedef stm32plus::net::NetworkLayer <
  DatalinkLayer,
  stm32plus::net::DefaultIp,
  stm32plus::net::Arp
  > NetworkLayer;
  typedef stm32plus::net::TransportLayer <
  NetworkLayer,
  stm32plus::net::Udp,
  stm32plus::net::Icmp
  > TransportLayer;
  typedef stm32plus::net::ApplicationLayer <
  TransportLayer,
  stm32plus::net::StaticIpClient,
  stm32plus::net::Ping
  > ApplicationLayer;
  typedef stm32plus::net::NetworkStack<ApplicationLayer> NetworkStack;

  typedef stm32plus::Rtc <
  stm32plus::RtcLsiClockFeature<stm32plus::Rtc32kHzLsiFrequencyProvider>,
            stm32plus::RtcSecondInterruptFeature
            > Rtc;

  NetworkStack net_;
  NetworkStack::Parameters params_;
  Rtc* rtc_;

The issue is that various PhyBase params don't seem to be getting set correctly. In GDB I do see the following PhyBase constructor get hit here.

The stacktrace for this location looks as follows:

#0  Parameters (
    __vtt_parm=0x8010be4 <VTT for stm32plus::net::ApplicationLayer<stm32plus::net::TransportLayer<stm32plus::net::NetworkLayer<stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>, stm32plus::net::DefaultIp, stm32plus::net::Arp>, stm32plus::net::Udp, stm32plus::net::Icmp>, stm32plus::net::StaticIpClient, stm32plus::net::Ping>::Parameters+20>, __in_chrg=0, this=0x2001feb4)
    at /usr/local/arm-none-eabi/include/stm32plus-040004/net/physical/lan8710a/LAN8710A.h:71
#1  Parameters (
    __vtt_parm=0x8010be4 <VTT for stm32plus::net::ApplicationLayer<stm32plus::net::TransportLayer<stm32plus::net::NetworkLayer<stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>, stm32plus::net::DefaultIp, stm32plus::net::Arp>, stm32plus::net::Udp, stm32plus::net::Icmp>, stm32plus::net::StaticIpClient, stm32plus::net::Ping>::Parameters+20>, this=0x2001feb4)
    at /usr/local/arm-none-eabi/include/stm32plus-040004/net/physical/lan8710a/LAN8710A.h:74
#2  Parameters (
    __vtt_parm=0x8010be0 <VTT for stm32plus::net::ApplicationLayer<stm32plus::net::TransportLayer<stm32plus::net::NetworkLayer<stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>, stm32plus::net::DefaultIp, stm32plus::net::Arp>, stm32plus::net::Udp, stm32plus::net::Icmp>, stm32plus::net::StaticIpClient, stm32plus::net::Ping>::Parameters+16>, __in_chrg=0, this=0x2001feb4)
    at /usr/local/arm-none-eabi/include/stm32plus-040004/net/physical/PhysicalLayer.h:32
#3  Parameters (
    __vtt_parm=0x8010be0 <VTT for stm32plus::net::ApplicationLayer<stm32plus::net::TransportLayer<stm32plus::net::NetworkLayer<stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>, stm32plus::net::DefaultIp, stm32plus::net::Arp>, stm32plus::net::Udp, stm32plus::net::Icmp>, stm32plus::net::StaticIpClient, stm32plus::net::Ping>::Parameters+16>, this=0x2001feb4)
    at /usr/local/arm-none-eabi/include/stm32plus-040004/net/physical/PhysicalLayer.h:32
#4  stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>::Parameters::Parameters (this=this@entry=0x2001feb4, __in_chrg=__in_chrg@entry=0, 
    __vtt_parm=__vtt_parm@entry=0x8010bdc <VTT for stm32plus::net::ApplicationLayer<stm32plus::net::TransportLayer<stm32plus::net::NetworkLayer<stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>, stm32plus::net::DefaultIp, stm32plus::net::Arp>, stm32plus::net::Udp, stm32plus::net::Icmp>, stm32plus::net::StaticIpClient, stm32plus::net::Ping>::Parameters+12>)
    at /usr/local/arm-none-eabi/include/stm32plus-040004/net/datalink/DatalinkLayer.h:31
#5  0x08001c20 in stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>::Parameters::Parameters (this=this@entry=0x2001feb4, 
    __vtt_parm=__vtt_parm@entry=0x8010bdc <VTT for stm32plus::net::ApplicationLayer<stm32plus::net::TransportLayer<stm32plus::net::NetworkLayer<stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>, stm32plus::net::DefaultIp, stm32plus::net::Arp>, stm32plus::net::Udp, stm32plus::net::Icmp>, stm32plus::net::StaticIpClient, stm32plus::net::Ping>::Parameters+12>)
    at /usr/local/arm-none-eabi/include/stm32plus-040004/net/datalink/DatalinkLayer.h:31
#6  0x08001c34 in Parameters (
    __vtt_parm=0x8010bd8 <VTT for stm32plus::net::ApplicationLayer<stm32plus::net::TransportLayer<stm32plus::net::NetworkLayer<stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>, stm32plus::net::DefaultIp, stm32plus::net::Arp>, stm32plus::net::Udp, stm32plus::net::Icmp>, stm32plus::net::StaticIpClient, stm32plus::net::Ping>::Parameters+8>, __in_chrg=0, this=0x2001feb4)
    at /usr/local/arm-none-eabi/include/stm32plus-040004/net/network/NetworkLayer.h:33
#7  stm32plus::net::NetworkLayer<stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>, stm32plus::net::DefaultIp, stm32plus::net::Arp>::Parameters::Parameters (this=this@entry=0x2001feb4, 
    __vtt_parm=__vtt_parm@entry=0x8010bd8 <VTT for stm32plus::net::ApplicationLayer<stm32plus::net::TransportLayer<stm32plus::net::NetworkLayer<stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>, stm32plus::net::DefaultIp, stm32plus::net::Arp>, stm32plus::net::Udp, stm32plus::net::Icmp>, stm32plus::net::StaticIpClient, stm32plus::net::Ping>::Parameters+8>)
    at /usr/local/arm-none-eabi/include/stm32plus-040004/net/network/NetworkLayer.h:33
#8  0x080027ba in Parameters (__vtt_parm=<optimized out>, __in_chrg=0, this=0x2001feb4)
    at /usr/local/arm-none-eabi/include/stm32plus-040004/net/transport/TransportLayer.h:34
#9  Parameters (__vtt_parm=<optimized out>, this=0x2001feb4)
    at /usr/local/arm-none-eabi/include/stm32plus-040004/net/transport/TransportLayer.h:34
#10 Parameters (__vtt_parm=0x0, __in_chrg=1, this=0x2001feb4)
#11 Parameters (this=0x2001feb4)
    at /usr/local/arm-none-eabi/include/stm32plus-040004/net/application/ApplicationLayer.h:33
#12 disco_firmware::NetworkTask::NetworkTask (this=0x2001fce4)
    at /home/modriscoll/workspace/firmware_ws/src/disco_firmware/firmware/src/tasks/network_task.cpp:46
#13 0x08000e2e in main () at /home/modriscoll/workspace/firmware_ws/src/disco_firmware/firmware/src/main.cpp:53

But when walking about out of the constructors for the net_ object I am seeing the following in gdb when I print net_ you can see that phy_resetDelay = 21267 and phy_duplexStatusBit = 8193 phy_speedStatusBit = 65533

$1 = {<stm32plus::net::ApplicationLayer<stm32plus::net::TransportLayer<stm32plus::net::NetworkLayer<stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>, stm32plus::net::DefaultIp, stm32plus::net::Arp>, stm32plus::net::Udp, stm32plus::net::Icmp>, stm32plus::net::StaticIpClient, stm32plus::net::Ping>> = {<stm32plus::net::TransportLayer<stm32plus::net::NetworkLayer<stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>, stm32plus::net::DefaultIp, stm32plus::net::Arp>, stm32plus::net::Udp, stm32plus::net::Icmp>> = {<stm32plus::net::NetworkLayer<stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>, stm32plus::net::DefaultIp, stm32plus::net::Arp>> = {<stm32plus::net::DatalinkLayer<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>, stm32plus::net::DefaultRmiiInterface, stm32plus::net::Mac>> = {<stm32plus::net::PhysicalLayer<stm32plus::net::LAN8710A>> = {<stm32plus::net::LAN8710A> = {<stm32plus::net::PhyBase> = {_params = {
                  phy_address = 1, phy_readTimeout = 5000, phy_writeTimeout = 5000, phy_resetDelay = 21267, 
                  phy_linkTimeout = 5000, phy_autoNegotiationTimeout = 5000, phy_duplexStatusBit = 8193, 
                  phy_speedStatusBit = 65533, phy_postConfigurationDelay = 10}, 
                _utilityObjects = 0x2001fe44}, <No data fields>}, <stm32plus::net::NetworkUtilityObjects> = {<stm32plus::net::NetworkReceiveEvents> = {NetworkReceiveEventSender = {_firstSlot = {

This is immediately during and after constructing a class that contains the net_ variable.
Stack track after it's finish constructing the net_ object:

#0  disco_firmware::NetworkTask::NetworkTask (this=0x2001fce4)
    at /home/modriscoll/workspace/firmware_ws/src/disco_firmware/firmware/src/tasks/network_task.cpp:53
#1  0x08000e2e in main () at /home/modriscoll/workspace/firmware_ws/src/disco_firmware/firmware/src/main.cpp:53

To note, this class is created within the context of a FreeRTOS task. But otherwise is fairly normal.

We are using a STM32F4 discovery board and it's associated Expansion board with Ethernet peripheral.

Any insight into why phy_speedStatusBit, phy_duplexStatusBit and phy_resetDelay are not being set correctly even though their constructor is run would be appreciated.

This is expected, although admittedly a little odd looking.

The constructor that you're following is the one called by the instantiation of the _params member in the PhyBase class. This constructor doesn't set values for the struct members that you've pointed out because they're going to be set in the 'initialise' phase.

For clarity it could set these values but it would be a waste of cycles and memory because when you declare your network stack's parameters object and call the initialise() method then the correct derivation of PhyBase is declared and its constructor always sets the values of those members in PhyBase to good values for that particular PHY. PhyBase::initialise() then takes a copy of that constructed structure and uses it from then on.

Thanks for taking a look @andysworkshop.

Something else is odd on my side. I don't believe this is stm32plus anymore and have isolated it to a context switch event when the stack gets smashed. Will close for now

Thanks.