This is the fourth part of the STM32 series. For your convenience you can find other parts in the table of contents in Part 1 – DES implementation

We have all the building blocks for STM32 server, so let’s write it.

Implementation

main.c

/*

*/

/* Includes */
#include 
#include "stm32f10x.h"
#include "STM32vldiscovery.h"
#include "ENC28J60.h"
#include "ip_arp_udp_tcp.h"
#include "simple_server.h"
#include "delay.h"

//NOTE: MAC address in ENC28J60 is byte-backward !!
const uint8_t ENC_MAC[6] = {0x54,0x55,0x58,0x10,0x00,0x24};
const uint8_t ENC_IP[4]={192,168,1,125};
uint8_t PC_MAC[6];
const uint8_t PC_IP[4]={192,168,1,1};

/* Private function prototypes */


extern int simple_server(void);

/* Private functions ---------------------------------------------------------*/

/* MAIN */
int main(void)
{
	Delay(0xFFFFF);

	SPI1_Init();
	enc28j60_init((uint8_t *)ENC_MAC);

	Delay(0xFFFFF);

    init_ip_arp_udp_tcp((uint8_t *)ENC_MAC, (uint8_t *)ENC_IP);

    Delay(0xFFFFF);

	enc28j60getrev();
    simple_server();
}

/*
 * Minimal __assert_func used by the assert() macro
 * */
void __assert_func(const char *file, int line, const char *func, const char *failedexpr)
{
  while(1)
  {}
}

/*
 * Minimal __assert() uses __assert__func()
 * */
void __assert(const char *file, int line, const char *failedexpr)
{
   __assert_func (file, line, NULL, failedexpr);
}


delay.c

#include "stm32f10x.h"
#include "delay.h"

void Delay(__IO uint32_t nTick)
{
  for(; nTick != 0; nTick--);
}

simple_server.c

#include "stdio.h"
#include 
#include "stm32f10x_conf.h"
#include "ENC28J60.h"
#include "net.h"
#include "ip_arp_udp_tcp.h"
#include "STM32vldiscovery.h"
#include "cipher.h"

#define PSTR(s) s

uint16_t my_udp_port = 50000; // listen port for udp
uint16_t my_udp_portResponse = 50001; // listen port for udp

#define BUFFER_SIZE 1500
static uint8_t buf[BUFFER_SIZE + 1];

uint16_t plen;
uint16_t dat_p;

int simple_server(void) {
	uint8_t cmd_pos = 0;
	uint8_t payloadlen = 0;
	char str[30];

	enc28j60_write_phy(PHLCON, 0x7a4);

	for(;;) {
		plen = enc28j60_recv_packet(buf, BUFFER_SIZE);

		if (plen == 0) {
			continue;
		}

		if (eth_type_is_arp_and_my_ip(buf, plen)) {
			make_arp_answer_from_request(buf);
			continue;
		}

		if (eth_type_is_ip_and_my_ip(buf, plen) == 0) {
			continue;
		}

		if (buf[IP_PROTO_P] == IP_PROTO_ICMP_V
				&& buf[ICMP_TYPE_P] == ICMP_TYPE_ECHOREQUEST_V) {
			make_echo_reply_from_request(buf, plen);
			continue;
		}

		uint16_t rPort = buf[UDP_DST_PORT_H_P]*256+buf[UDP_DST_PORT_L_P];
		uint8_t dataBuffer[220] = {0};

		if (buf[IP_PROTO_P] == IP_PROTO_UDP_V) {
			payloadlen = buf[UDP_LEN_L_P] - UDP_HEADER_LEN;

			if(rPort == my_udp_port) {
				cipher(&buf[UDP_DATA_P], dataBuffer, payloadlen, 0xaaaaaaaaaaaaaaaa);
				make_udp_reply_from_request(buf, dataBuffer, payloadlen, &my_udp_portResponse);
			}
			else if(rPort == my_udp_portResponse) {
				decipher(&buf[UDP_DATA_P], dataBuffer, payloadlen, 0xaaaaaaaaaaaaaaaa);
				make_udp_reply_from_request(buf, dataBuffer, payloadlen, &my_udp_port);
			}
		}
	}
} 

And it looks like this is it.

Summary

We have everything in place. We know how to encrypt data using DES, we have Swing chat application for tests and we have application for STM32 to actually do the job. It is easy and most of the stuff is hardcoded, however, it could be easily modified just to do the remaining 20% of the work.