ENC28J60 + UIP + STM32 for ICMP (ping) operation usage records

Posted by mickro on Sat, 01 Jan 2022 20:22:38 +0100

Last described how ENC28J60 wrote the first Hello World on STM32, this time based on the last modification of the driver, using UIP to achieve ARP package response, ICMP response (ping pass MCU)

UIPgitee download address: https://gitee.com/jinling_gitee/uip.git Github address: https://github.com/adamdunkels/uip

After downloading, the project path is as follows:

 

When using UIP, you need to modify something to work properly:

1. Modify the uip-conf.h file, which is some configuration files that UIP is open to users

2. Declare UIP_APPCALL, uip_log callback function

3. Implement tapdev. Tapdev_declared under H header file Init ENC28J60 initialization, tapdev_read: Read a package of data, tapdev_send Send a package of data functions

 

 

Mainly uses files under the UIP folder, and also uses uip-conf.h, tapdev under the unix folder. H.

Modify uip-conf.h

Make some changes to uip-conf.h to work properly:

1. Comment on webserver.h Introduce header file

 

 

Implement UIP_APPCALL, uip_log function

These two functions are callback functions of UIP, this time only to use UIP ping to pass MCU, so they are implemented as empty functions:

In main. Two functions are declared in c, corresponding to UIP_APPCALL and uip_log, and timer. Clock_called in C Time

....
//UIP_APPCALL
void main_appcall(){
    
}
//UIP_APPCALL
void main_uiplog(char* msg) {
    
}
int clock_time(){
    
}

.....

Go back to uip-conf.h and declare UIP_APPCALL and uip_log implementation function is main_appcall and main_uiplog:

#define UIP_APPCALL main_appcall
#define uip_log main_uiplog

clock_time function, already in clock. Declaration in h, just not implemented, so there is no need to repeat declaration here

Uipopt. Declare uip_in H Tcp_ Appstate_ T appstate type

In uipopt.h 503 line position with commented out uip_tcp_appstate_t Declaration, open here:

 

 

Or go to uip.h Comment off using uip_tcp_appstate_t position:

Implement tapdev_init, tapdev_read, tapdev_send function

Create a new tapdev.c, as follows:

#include <tapdev.h>
#include "enc28j60.h"//ENC28J60 Driver
#include <uip.h>

//Reference to external files uip.c Declared in uip_ethaddr
extern struct uip_eth_addr uip_ethaddr;
//network address
unsigned char my_mac[6] = {0x29, 0x7C, 0x07, 0x37, 0x24, 0x63};
void tapdev_init(void) {
    enc28j60_init(my_mac);
    for (int i = 0; i < 6; i++)
    {
     uip_ethaddr.addr[i] = my_mac[i];
    }
}
//Read a package of data
unsigned int tapdev_read(void){
    enc28j60_packet_receive(uip_buf, MAX_FRAMELEN);
}
//Send a package of data
void tapdev_send(void) {
    enc28j60_packet_send(uip_buf, MAX_FRAMELEN);
}

Put UIP related files together

Finally, the above mentioned unix/uip-conf.h, unix/tapdev.h into the UIP folder, set the header file path to the UIP folder through IDE(keil5)

keil5 adds to the red box shown below. c File

 

 

Modify each. c file, change "" to <>, for example:

 

 

main.c Implement arp response and icmp response

Before that, you need to ensure that the above files can be compiled and passed properly after you add them:

First at mainc. UIP_declaring UIP in C BUF:

#define UIP_BUF ((struct uip_eth_hdr *)&uip_buf[0])

Processing ICMP request operation:

int main(void)
{
  /* USER CODE BEGIN 1 */

  /* USER CODE END 1 */
  

  /* MCU Configuration--------------------------------------------------------*/

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
  HAL_Init();

  /* USER CODE BEGIN Init */

  /* USER CODE END Init */

  /* Configure the system clock */
  SystemClock_Config();

  /* USER CODE BEGIN SysInit */

  /* USER CODE END SysInit */

  /* Initialize all configured peripherals */
  MX_GPIO_Init();
  MX_SPI1_Init();
  MX_USART1_UART_Init();
  /* USER CODE BEGIN 2 */
    //Wait some time before initialization
    for(int i = 0;i < 20;i++) {
        //enc28j60PhyWrite(PHLCON,0x7a4);    
        HAL_Delay(500);
        print("begin init enc28j60...");
    }
    tapdev_init();//Initialization enc28j60
    print("init enc28j60 success!");
    //Initialization UIP
    uip_init();
    uip_ipaddr_t ipaddr;
    uip_ipaddr(ipaddr, 192, 168, 1, 8);//MCU IP address
    uip_sethostaddr(ipaddr);
    uip_ipaddr(ipaddr, 192, 168, 1, 1);//gateway,Computers and MCU Use when passing router
    uip_setdraddr(ipaddr);
    uip_ipaddr(ipaddr, 255, 255, 252, 0);//Subnet Mask
    uip_setnetmask(ipaddr);
  /* USER CODE END 2 */

  /* Infinite loop */
  /* USER CODE BEGIN WHILE */
  while (1)
  {
    /* USER CODE END WHILE */
        //Try to read a package of data
        uip_len = tapdev_read();
        if(uip_len == 0){
            //No data read
            continue;
        }
        //Is it ARP request
        if(UIP_BUF->type == htons(UIP_ETHTYPE_ARP)) {
            //Assembly ARP Respond to requests
            uip_arp_arpin();
            if(uip_len>0){
                //response ARP Request to send data
                tapdev_send();
            }
        }
        //Is it IPV4
        if(UIP_BUF->type == htons(UIP_ETHTYPE_IP)) {
            uip_arp_ipin();
            //UIP Parse data
            uip_input();
            if(uip_len > 0){
                //Must be called, otherwise it will appear ping Incomplete, use the package capture tool to see that received packets checksum bad Checksum Failure
                uip_arp_out();
                tapdev_send();
            }
        }
    /* USER CODE BEGIN 3 */
  }
  /* USER CODE END 3 */
}

After the MCU is linked on the computer side, you need to turn on the network device and set it to use the following IP:

 

 

 

Finally, a successful PingTong MCU device Keil5 project is attached for reference: https://wwb.lanzouw.com/itg8Ly0k6id Password: 5nhb

Topics: stm32