Skip to main content
sa.2
Associate
January 5, 2023
Question

MDIO bit banging data rate Hello, We have implemented MDIO(Management Data Input/Output) protocol by bit banging in the STM32 Nucleo-L series board and the corresponding frequency of MDIO is 2.8MHz as of now.

  • January 5, 2023
  • 5 replies
  • 4558 views

My requirement is to increase this frequency since the MCU operates at 110MHz. Kindly share your ideas ! --regards

0693W00000Y7SIcQAN.png

    This topic has been closed for replies.

    5 replies

    Bob S
    Super User
    January 6, 2023

    While L series part? L0? L4? L5? And what frequency are you trying to reach? Or is it just a poorly-defined "go faster"? And why does it need to be faster? MDIO PHY access isn't usually THAT much of a time critical thing.

    110MHz CPU clock and 2.8MHz bitbang clock rate means 39 CPU cycles per bitbang clock pulse. That isn't much, and that ignores any additional cycles that may be spent with FLASH wait states and/or RAM access delays through the switch fabric (including stack push/pop on function calls).

    But without seeing your code there is not much we can suggest beyond generic things - higher compiler optimizations, are interrupts slowing things down, remove function calls and in-line everything, careful placement of stack and variables CCM RAM, move code from FLASH into RAM, pre-compute the bitstream and use DMA to the GPIO port.

    Tesla DeLorean
    Guru
    January 6, 2023

    110MHz L5 most likely

    What speed do you need? Could you do efficiently with CPLD/FPGA ?

    The comment was edited to adhere the community guidelines.

    Tips, Buy me a coffee, or three.. PayPal VenmoUp vote any posts that you find helpful, it shows what's working..
    VThan.2
    Associate III
    January 17, 2023

    Hello,

    Thank you for replying to my team mate's question. Here is the code for MDIO write and read. The MCU we are using is STM32L552MEY6

    void OUT (unsigned long data, unsigned char p) 

    {

    unsigned char j;

      // Output a value to the management interface.

      data <<= (32 - p);

      for ( j=0; j<p; j++ ) 

        if (data & 0x80000000)//0x80000000=true? 1010 & 1000,0100 & 1000=0,1000 & 1000 =1,0000 

          {

          //SET_MDIO_PIN_HIGH;

          HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,1);

    }

        else

          {

          //SET_MDIO_PIN_LOW;

    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_4,0);

          }

    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,1);   

    HAL_GPIO_WritePin(GPIOB,GPIO_PIN_2,0);

         

        data <<= 1;

         

        }

    void WRITE( unsigned int phy_ad, unsigned int reg_ad,unsigned int Value)// mdio write

    {

    OUT(0xFFFFFFFF, 32);

    OUT (0x00000005, 4);

    OUT ((unsigned long)phy_ad, 5);

    OUT ((unsigned long)reg_ad, 5);

    OUT(0x02, 2); // turnaround time 

    OUT(Value, 0xFDAC);// 16 bit data

    }

    Just thinking about FPGA to do this more efficiently. Just trying to understand when to make that pivot? The board contains one MCU pinging 5 PHY chipsets and reporting data over serial protocol to a GUI.

    Danish1
    Lead III
    January 17, 2023

    Looking at your code, I see frequent calls to HAL_GPIO_WritePin()

    Remember that's a function, for which you'll have a function-call and all the processor-overheads that it involves.

    The fastest way to set a bit in a port is by writing directly to GPIOx->BSRR

    To set bit 0 in GPIOB you would do

    GPIOB->BSRR = 1;

    And to clear that bit you would do

    GPIOB->BSRR = 0x10000;

    To get a better understanding of what's going on here, I strongly recommend that you read chapter on General Purpose I/Os (GPIO) in the Reference Manual for your stm32. You could also look at the source code for HAL_GPIO_WritePin(), which might be something like (here it is from stm32l4xx_hal_gpio.c)

    /**
     * @brief Set or clear the selected data port bit.
     *
     * @note This function uses GPIOx_BSRR and GPIOx_BRR registers to allow atomic read/modify
     * accesses. In this way, there is no risk of an IRQ occurring between
     * the read and the modify access.
     *
     * @param GPIOx where x can be (A..H) to select the GPIO peripheral for STM32L4 family
     * @param GPIO_Pin specifies the port bit to be written.
     * This parameter can be any combination of GPIO_Pin_x where x can be (0..15).
     * @param PinState specifies the value to be written to the selected bit.
     * This parameter can be one of the GPIO_PinState enum values:
     * @arg GPIO_PIN_RESET: to clear the port pin
     * @arg GPIO_PIN_SET: to set the port pin
     * @retval None
     */
    void HAL_GPIO_WritePin(GPIO_TypeDef* GPIOx, uint16_t GPIO_Pin, GPIO_PinState PinState)
    {
     /* Check the parameters */
     assert_param(IS_GPIO_PIN(GPIO_Pin));
     assert_param(IS_GPIO_PIN_ACTION(PinState));
     
     if(PinState != GPIO_PIN_RESET)
     {
     GPIOx->BSRR = (uint32_t)GPIO_Pin;
     }
     else
     {
     GPIOx->BRR = (uint32_t)GPIO_Pin;
     }
    }

    Edit: Note that BRR is simply a 16-bit access to the high 16-bits of BSRR.

    Depending whether you are in Debug or Release builds, and what optimisations you selected, the asserts might be ignored altogether, but you are still wasting processor-cycles by having a function-call and an if-statement.

    Regards,

    Danish

    sa.2
    sa.2Author
    Associate
    January 17, 2023

    Hello Danish,

    Thanks for your reply, yes have been into looking the reference manual of our particular board and thereby "SET" the BSRR reg and got pull down frequency from 2.6Mhz to 250 Hz. I know it should increase as you said earlier (by eliminating the function call for HAL_WRITE_PIN). Kindly share your thoughts on these anomalies!

    0693W00000Y8RBiQAN.jpgCode:

    while (1)

     {

     

    GPIOB->BSRR = (uint32_t) GPIO_PIN_6;

    GPIOB->BSRR = (uint32_t) GPIO_PIN_6 << 16U;

    }

    Note: Just trying to toggle the GPIO pin 6 and then if it meets our requirements can implement the same in MDIO fun calls !!

    regards

    Sa.2

    gbm
    Lead III
    January 17, 2023

    Replace the body of your loop with:

    GPIOB->BSRR = data & 0x80000000 ? GPIO_PIN_4 : GPIO_PIN_4 << 16;

    data <<= 1;

    My STM32 stuff on github - compact USB device stack and more: https://github.com/gbm-ii/gbmUSBdevice