Power Mode of W5500

IoT devices are often working remotely. Therefore, power efficiency is always one of the considerations when developing an IoT device. W5500, like other chips do, has power mode functions so that users can choose whatever mode they want for their own sake.

The following tutorial demonstrates how to change the power mode of W5500, and some precautions about changing mode when your programme is running.



Before burning the bin file into your EVB:

      1. Connect W5500 EVB to the router/NAT that you are using, or any other device that allows you to connect to the internet
      2. Manually change the Network configuration:
          • Go to the definition of function “set_default()” (Should be inside device.c), make sure the subnet mask, local IP address, gateway and DNS are set according to the internet setting you are using with your router/NAT
      3. Rebuild the sample code and burn it into W5500EVB
      4. Change your PC’s IP address to a static IP if you are not using router


Testing Procedure

  • The button for external internal is PA04 in Iuput-Pull-Up mode. you may also check the External Interrupt Configuration “EXTI_Config()” yourself for better understanding.
  • It is strongly advised to pay much attention to “Remark” at the bottom of this page before testing.
  • After burning the firmware into W5500EVB, open serial port and reset your EVB. Press button PA4 only after the printf message “****Initialization done****” was shown.


Understanding Hardware Structure

Since the tutorial is more on hardware than on software, to be able to change the power mode we need to first understand a bit about the related register, PHYCFGR (PHY Configuration Register).

The first three LSBs are read-only bits, therefore we do not have to care about it when changing power mode. For the others:

  • RST(bit 7): Reset bit. It should always be 1 unless reset of PHY is required. Once PHY is reset, this bit would automatically be set to 1.

  • OPMD(bit 6):Configure PHY Operation Mode. It is zero by default. Once user change the power mode, it must be set as 1 in order to activate the Operation Mode Configuration

  • OPMDC(bit 3-5): Operation Mode Configuration Bit. These bits select the operation mode of PHY shown in the following table.

The following is a brief table showing the default value of PHYCFGR in binary number(0xba in Hex, when all first LSB are 0):

RST(bit 7)OPMD(bit 6)OPMDC(bit 3-5)DPX(bit 2)SPD(bit 1)LNK(bit 0)
10111xxx

For more detail on specification of the modes, please refer to the Chapter 5.4 of the datasheet of W5500.

Basically, to change the power mode of W5500, you should first reset the PHYCFGR, then set the register again according to the table based on what mode you would like to change to. To achieve this, you may simply just add the following two codes:

IINCHIP_WRITE(PHYCFGR,0x7F);   // Reset PHYCFGR, must be done whenever changing the Power Mode
IINCHIP_WRITE(PHYCFGR,0xE0);   // 0xXX is the number according to your power mode selection


More detail would be shown in Code Explanation.


Code Explanation

The sample code you can download on this page consists of three parts:

  • Code for changing power modes before going into main loop(some of them are commented for you to select)
  • TCP Server for you to demonstrate the effect of each power mode under normal TCP data transmission
  • Code for External interrupt, which allows you to change the power mode when being inside the main loop

The following table shows some behaviors of the PHYCFGR’s Value 


PHYCFG’s Value when connectedPHYCFG’s Value when disconnected
Default Mode0xBF / 0xFF0xBA
Power Down Mode0xF70xF0
10BT Full-duplex 0xCD0xCC
100BT Half-duplex 0xD3 0xD2
100BT Full-duplex 0xDF 0xDE

Let’s go down to the code for more details:

int main(void)
{
  uint16 local_port=6000;
  uint16 len=0; 													
  uint8 phyconf=0;		  
  Systick_Init(72);	
  GPIO_Configuration();
  USART1_Init(); 		
  WIZ_SPI_Init();
  erase_eeprom(0,255);
  at24c16_init();
  Reset_W5500();
  set_default();
  set_network();
  setkeepalive(0);

  EXTI_Config();
  printf("TCP Server Port:%d\r\n",local_port);
  printf("W5500 Init Complete!\r\n");
  printf("Start TCP Server Test!\r\n"); 
	
  phyconf=IINCHIP_READ(PHYCFGR);
  printf("phy1=0x%x\r\n",phyconf);
	
  printf("phy s/w reset\r\n");
  Delay_ms(5000);
  Delay_ms(5000);
  printf("\r\n****Initialization done****\r\n\r\n");	
/****************





 Necessary Initialization






 Initialization of W5500


 Initialization of External Interrupt
 (with further explanation below)




 Read and show the value of PHYCFGR
 (with further explanation below)



****************/
while(1)
{
  switch(getSn_SR(0))
  {
    case SOCK_INIT:	
      Delay_ms(500);
      listen(0);
      break;

    case SOCK_ESTABLISHED:
      if(getSn_IR(0) & Sn_IR_CON)
      {
        setSn_IR(0, Sn_IR_CON);
      }

      len=getSn_RX_RSR(0);

      if(len>0)
      {
        recv(0,buffer,len);
        printf("%s\r\n",buffer);
        memset(buffer,0,len+1);
      }

      if(USART_RX_STA & 0x8000)
      {					   
        len = USART_RX_STA & 0x3fff;
        send(0,USART_RX_BUF,len);
        USART_RX_STA = 0;
        memset(USART_RX_BUF,0,len+1);
      }
      break;

    case SOCK_CLOSE_WAIT:
      close(0);
      break;

    case SOCK_CLOSED:
      socket(0,Sn_MR_TCP,local_port,Sn_MR_ND);
      break;
  }
 }
}


External Interrupt

Up to here, you may have discovered already that there is no difference between this main() and the one of TCP Client’s tutorial. Yes, they are literally almost the same, except the additional code of printing out the value of register PHYCFGR and initialization of external interrupt, which have been pointed out above. The focus of this tutorial is written in external interrupt in “stm32f10x_it.c”.

There is a function that you should pay attention to: changePHY().

void EXTI4_IRQHandler(void) {

  if(EXTI_GetITStatus(EXTI_Line4) != RESET) {

  /** LED PA2 indicates the external interrupted triggered**/
    if (GPIO_ReadOutputDataBit(GPIOA, GPIO_Pin_2) == (uint8_t)Bit_SET){
      GPIO_ResetBits(GPIOA, GPIO_Pin_2);
    }
    else {
      GPIO_SetBits(GPIOA, GPIO_Pin_2);
    }
			
    printf("\r\n\r\n**********External interrupt triggered*********\r\n\r\n");
    printf("Please wait for a second");
			
    Delay_ms(2000);    printf(".");
    Delay_ms(2000);    printf(".");
    Delay_ms(2000);    printf(".");
    Delay_ms(2000);    printf(".");
    Delay_ms(2000);    printf(".");
    Delay_ms(2000);    printf(".        \r\n\r\n");
			
    //printf("Now enter into ChangePHY() function \r\n\r\n");
    changePHY(); //<======= This is the function doing the Power Mode changing
    //printf("ChangePHY Ended \r\n");
    //printf("Interrupt Ended\r\n\r\n\r\n");
    //socket(0,Sn_MR_TCP,6000,Sn_MR_ND);
    Delay_ms(2000);
    printf("***********************************************\r\n\r\n");

    EXTI_ClearITPendingBit(EXTI_Line4);
  }
}


The following is the code for changing Power Mode in way of external interrupt. As mentioned above, changing power mode technically requires two lines of code. Nevertheless, arranging the code in the way shown below helps better test the power mode function as a whole, as well as indicates how changing power mode can be done under various conditions.

Simply by understanding the IF conditions and “printf messages” can you comprehend the mode and the algorithm of the function. You may as well take a quick look at the function of “Re_configw5500()” by yourself for better understanding.

void changePHY(){
  uint8 phyconf = 0;	
  //close(0);
  phyconf=IINCHIP_READ(PHYCFGR);
	
  printf("The value of PHYCFGR before changing Power Mode is: 0x%x \r\n\r\n",phyconf);
  //close(0);	

  if(((phyconf=IINCHIP_READ(PHYCFGR)) == 0xBA)||((phyconf=IINCHIP_READ(PHYCFGR))== 0xBF)){
    //close(0);
    Delay_ms(2000);
    IINCHIP_WRITE(PHYCFGR,0x7F);
    IINCHIP_WRITE(PHYCFGR,0xD0);
    phyconf=IINCHIP_READ(PHYCFGR);
    printf("Bits have changed.\r\n");
    printf("PHYCFGR = 0x%x, the power mode is now: 100BT Half-duplex no auto \r\n\r\n",phyconf);
    //close(0);
  }
		
  else if (((phyconf=IINCHIP_READ(PHYCFGR))== 0xD3)||( (phyconf=IINCHIP_READ(PHYCFGR))== 0xD2)){ 
    //close(0);
    Delay_ms(2000);
    IINCHIP_WRITE(PHYCFGR,0x7F);
    IINCHIP_WRITE(PHYCFGR,0xF7);
    phyconf=IINCHIP_READ(PHYCFGR);	
    printf("Bits have changed.\r\n");
    printf("PHYCFGR = 0x%x, the power mode is now: Power Down Mode \r\n\r\n",phyconf);
    //close(0);
  }

  else if (((phyconf=IINCHIP_READ(PHYCFGR))== 0xF9)||( (phyconf=IINCHIP_READ(PHYCFGR))== 0xF0)){ 
    //close(0);
    Delay_ms(2000);
    IINCHIP_WRITE(PHYCFGR,0x7F);
    IINCHIP_WRITE(PHYCFGR,0xCF);
    phyconf=IINCHIP_READ(PHYCFGR);	
    printf("Bits have changed.\r\n");
    printf("PHYCFGR = 0x%x, the power mode is now: 10BT Full-duplex no auto \r\n\r\n",phyconf);
  }
		
  else if (((phyconf=IINCHIP_READ(PHYCFGR))== 0xCC)||( (phyconf=IINCHIP_READ(PHYCFGR))== 0xCD)){ 
    //close(0);
    Delay_ms(2000);
    IINCHIP_WRITE(PHYCFGR,0x7F);
    IINCHIP_WRITE(PHYCFGR,0xDF);
    phyconf=IINCHIP_READ(PHYCFGR);	
    printf("Bits have changed.\r\n");
    printf("PHYCFGR = 0x%x, the power mode is now: 100BT Full-duplex no auto \r\n\r\n",phyconf);
  }		
		
  else if ((phyconf=IINCHIP_READ(PHYCFGR)) == 0xDF||(phyconf=IINCHIP_READ(PHYCFGR)) == 0xDE){ 
    printf("Reset W5500");
    close(0);
    Delay_ms(2000);    printf(".");
    Delay_ms(2000);    printf(".");
    Delay_ms(2000);    printf(".");
    Delay_ms(2000);    printf(".");

    Re_configw5500();  // <==Include all necessary procedure when reset W5500

    phyconf=IINCHIP_READ(PHYCFGR);
    printf("After reset, phy=0x%x \r\n",phyconf);
  }
		
  else printf("No action for phy=0x%x, ended changePHY()..\r\n",IINCHIP_READ(PHYCFGR));
		
  //printf("\r\nInterrupt Service Routine ended.\r\nGoing back to main loop now\r\n\r\n");

}



Remarks

Since the changing-power-mode thing is more on physical side, there are quite a lot of precautions to be aware of in order to cope with the hardware, as shown below:

  • Power Mode should not be changed when during the function ‘listen()’ and there is no internet connection, otherwise error may happen

  • Prevent changing the Power Mode when socket is connected

  • No action other than reset W5500 can be done when W5500 is in Power Down Mode. Please be remembered to reset W5500 if you have ever switched it into Power Down Mode.

  • The value of the register of Power Down Mode, especially when no socket is opened, varies. Beware of this behaviour. It is advised to test the sample code until you fully comprehend the behaviour of Power Mode Changing before writing your own code

  • The Function in External ISR would reset W5500 if it is in Power Down Mode. Please try pressing the button several times since it may not be able to catch the value of PHYCFGR in Power Down Mode

  • The function “close()” must not be run when the corresponding socket is closed, or if W5500 is in Power Down Mode



Download