element14 Community
element14 Community
    Register Log In
  • Site
  • Search
  • Log In Register
  • Community Hub
    Community Hub
    • What's New on element14
    • Feedback and Support
    • Benefits of Membership
    • Personal Blogs
    • Members Area
    • Achievement Levels
  • Learn
    Learn
    • Ask an Expert
    • eBooks
    • element14 presents
    • Learning Center
    • Tech Spotlight
    • STEM Academy
    • Webinars, Training and Events
    • Learning Groups
  • Technologies
    Technologies
    • 3D Printing
    • FPGA
    • Industrial Automation
    • Internet of Things
    • Power & Energy
    • Sensors
    • Technology Groups
  • Challenges & Projects
    Challenges & Projects
    • Design Challenges
    • element14 presents Projects
    • Project14
    • Arduino Projects
    • Raspberry Pi Projects
    • Project Groups
  • Products
    Products
    • Arduino
    • Avnet & Tria Boards Community
    • Dev Tools
    • Manufacturers
    • Multicomp Pro
    • Product Groups
    • Raspberry Pi
    • RoadTests & Reviews
  • About Us
  • Store
    Store
    • Visit Your Store
    • Choose another store...
      • Europe
      •  Austria (German)
      •  Belgium (Dutch, French)
      •  Bulgaria (Bulgarian)
      •  Czech Republic (Czech)
      •  Denmark (Danish)
      •  Estonia (Estonian)
      •  Finland (Finnish)
      •  France (French)
      •  Germany (German)
      •  Hungary (Hungarian)
      •  Ireland
      •  Israel
      •  Italy (Italian)
      •  Latvia (Latvian)
      •  
      •  Lithuania (Lithuanian)
      •  Netherlands (Dutch)
      •  Norway (Norwegian)
      •  Poland (Polish)
      •  Portugal (Portuguese)
      •  Romania (Romanian)
      •  Russia (Russian)
      •  Slovakia (Slovak)
      •  Slovenia (Slovenian)
      •  Spain (Spanish)
      •  Sweden (Swedish)
      •  Switzerland(German, French)
      •  Turkey (Turkish)
      •  United Kingdom
      • Asia Pacific
      •  Australia
      •  China
      •  Hong Kong
      •  India
      •  Korea (Korean)
      •  Malaysia
      •  New Zealand
      •  Philippines
      •  Singapore
      •  Taiwan
      •  Thailand (Thai)
      • Americas
      •  Brazil (Portuguese)
      •  Canada
      •  Mexico (Spanish)
      •  United States
      Can't find the country/region you're looking for? Visit our export site or find a local distributor.
  • Translate
  • Profile
  • Settings
Freedom development platform
  • Products
  • Dev Tools
  • Freedom development platform
  • More
  • Cancel
Freedom development platform
Documents Interfacing FRDM-KL25Z with Arduino Ethernet Shield R3 on Processor Expert, Part 3: Embedded Web Server
  • Blog
  • Forum
  • Documents
  • Files
  • Members
  • Mentions
  • Sub-Groups
  • Tags
  • More
  • Cancel
  • New
Join Freedom development platform to participate - click to join for free!
Actions
  • Share
  • More
  • Cancel
Engagement
  • Author Author: bheemarao
  • Date Created: 11 Mar 2014 10:26 AM Date Created
  • Last Updated Last Updated: 18 Mar 2014 1:28 PM
  • Views 869 views
  • Likes 0 likes
  • Comments 0 comments
Related
Recommended

Interfacing FRDM-KL25Z with Arduino Ethernet Shield R3 on Processor Expert, Part 3: Embedded Web Server

This tutorial was extracted from Erich Styger blog http://mcuoneclipse.wordpress.com with his agreement.

This is Part 3 of an ongoing tutorial to use the Arduino Ethernet Shield R3 with a Freescale FRDM-KL25Z board (or any other board you like).

In Part 1 I worked on the SD card, in Part 2 I have added basic network connection. Now time to run a web server with my FRDM-KL25ZFRDM-KL25Z image. With this, I can get access to my board through the network, and the board will host a web page where I can do pretty much everything: showing status, or adding functions to turn on things like an LED.

          Web Server with W5100 on FRDM-KL25Z

                              Web Server with W5100 on FRDM-KL25Z

 

List of Tutorials

  1. FRDM with Arduino Ethernet Shield R3, Part 1: SD Card
  2. FRDM with Arduino Ethernet Shield R3, Part 2: Ping
  3. FRDM with Arduino Ethernet Shield R3, Part 3: Embedded Web Server

W5100 as Web Server

The Wiznet W5100 Ethernet Chip on the Arduino Ethernet Shield R3Arduino Ethernet Shield R3 makes it easy to host a web server with a small microcontroller: the heavy protocol lifting is implemented in the W5100.


                                                  image


FRDM-KL25Z running Embedded Web Server with W5100


To make a web server, I need 3 things to do:

  1. Initialize the W5100
  2. Using Sockets
  3. Host an HTML web server

There are many good tutorials around this subject available. I recommend “Integrating Wiznet W5100, WIZ811MJ network module with Atmel AVR Microcontroller” as this article describes very nicely the features of the device and how the socket interface works. The example used in that article implements only one socket, while I have extended it to support up to four sockets of the device with the help of this article: “Wiznet 5100 library for ATmega devices“.

Initialization

First, the W5100 needs to be initialized:

  1. Reset the device
  2. Configure the network address and gateway
  3. Set up the total 8 KByte send and receive buffers for the 4 sockets

:idea: All the source files are available on GitHub.


 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

  static void WiznetSetup(void) {

  CLS1_SendStr((unsigned char*)"Reset W5100.\r\n", CLS1_GetStdio()->stdOut);

  /* reset device */

  if (W5100_MemWriteByte(W5100_MR, W5100_MR_BIT_RST)!=ERR_OK) {

    CLS1_SendStr((unsigned char*)"Failed to reset device!\r\n", CLS1_GetStdio()->stdErr);

  }

  CLS1_SendStr((unsigned char*)"Configure network.\r\n", CLS1_GetStdio()->stdOut);

  /* configure network: IP address, gateway, netmask, MAC */

  if (W5100_WriteConfig((w5100_config_t*)&W5100_config)!=ERR_OK) {

    CLS1_SendStr((unsigned char*)"Failed to set Net Configuration!\r\n", CLS1_GetStdio()->stdErr);

  }

  CLS1_SendStr((unsigned char*)"Configure RX/TX memory.\r\n", CLS1_GetStdio()->stdOut);

  /* we have 8 KByte we can use for the RX and TX sockets: */

  if (W5100_MemWriteByte(W5100_RMSR,

       W5100_xMSR_SOCKET_1_MEM_SIZE_2KB

      |W5100_xMSR_SOCKET_2_MEM_SIZE_2KB

      |W5100_xMSR_SOCKET_3_MEM_SIZE_2KB

      |W5100_xMSR_SOCKET_4_MEM_SIZE_2KB

     )!=ERR_OK)

  {

    CLS1_SendStr((unsigned char*)"Failed to set RX socket memory size!\r\n", CLS1_GetStdio()->stdErr);

  }

  if (W5100_MemWriteByte(W5100_TMSR,

       W5100_xMSR_SOCKET_1_MEM_SIZE_2KB

      |W5100_xMSR_SOCKET_2_MEM_SIZE_2KB

      |W5100_xMSR_SOCKET_3_MEM_SIZE_2KB

      |W5100_xMSR_SOCKET_4_MEM_SIZE_2KB

     )!=ERR_OK)

  {

    CLS1_SendStr((unsigned char*)"Failed to set TX socket memory size!\r\n", CLS1_GetStdio()->stdErr);

  }

  CLS1_SendStr((unsigned char*)"done!\r\n", CLS1_GetStdio()->stdOut);

}

Sockets

 

The W5100 supports up to 4 sockets. For this I have ‘sockets.h’ and ‘sockets.c’.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

  /*!

  * \brief Opens a socket

* \param sock

* \param eth_protocol Ethernet protocol for the socket (TCP, UPD, PPPOE, ...)

* \param tcp_port TCP port to be used (typically 80 for HTTP)

* \return Error code, ERR_OK for success

*/

uint8_t SOCK_OpenSocket(uint8_t sock, uint8_t eth_protocol, uint16_t tcp_port);

 

/*!

* \brief Starts listening on the socket.

* \param sock Socket number, 0..W5100_NUM_SOCKETS.

* \return Error code, ERR_OK for success

*/

uint8_t SOCK_Listen(uint8_t sock);

 

/*!

* \brief Returns the socket status

* \param sock Socket number, 0..W5100_NUM_SOCKETS.

* \param status Pointer to where to store the status.

* \return Error code, ERR_OK for success

*/

uint8_t SOCK_GetStatus(uint8_t sock, uint8_t *status);

 

/*!

* \brief Returns the received data size in the socket.

* \param sock Socket number, 0..W5100_NUM_SOCKETS.

* \param rxSize Pointer to where to store the amount bytes in socket.

* \return Error code, ERR_OK for success

*/

uint8_t SOCK_ReceivedSize(uint8_t sock, uint16_t *rxSize);

 

/*!

* \brief Receive data from a socket

* \param sock Socket number, 0..W5100_NUM_SOCKETS

* \param buf Pointer to buffer with data

* \param bufSize Size of buf in bytes

* \param readLen Size of data to read in bytes

* \return Error code, ERR_OK for success

*/

uint8_t SOCK_Receive(uint8_t sock, uint8_t *buf, size_t bufSize, size_t readLen);

 

/*!

* \brief Send data to a socket

* \param sock Socket number, 0..W5100_NUM_SOCKETS

* \param buf Pointer to buffer with data

* \param bufLen Size of data in bytes

* \return Error code, ERR_OK for success

*/

uint8_t SOCK_Send(uint8_t sock, const uint8_t *buf, size_t buflen);

 

/*!

* \brief Disconnects a socket

* \param sock Socket number, 0..W5100_NUM_SOCKETS

* \return Error code, ERR_OK for success

*/

uint8_t SOCK_Disconnect(uint8_t sock);

 

/*!

* \brief Close a socket

* \param sock Socket number, 0..W5100_NUM_SOCKETS

*/

uint8_t SOCK_CloseSocket(uint8_t sock);

 

/*!

* \brief Driver initialization.

*/

void SOCK_Init(void);

 

/*!

* \brief Driver de-initialization.

*/

void SOCK_Deinit(void);

The implementation uses the W5100 low-level driver I presented in Part 2:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

  #include "socket.h"

  #include "w5100.h"

#include "WAIT1.h"

 

uint8_t SOCK_CloseSocket(uint8_t sock) {

  uint8_t val;

  uint16_t sockaddr;

 

  if (sock>=W5100_NUM_SOCKETS) {

    return ERR_VALUE;

  }

  sockaddr = W5100_SKT_BASE(sock);

  /* Send Close Command */

  W5100_MemWriteByte(sockaddr+W5100_CR_OFFSET, W5100_CR_CLOSE);

  do { /* Waiting until the S0_CR is clear */

    W5100_MemReadByte(sockaddr+W5100_CR_OFFSET, &val);

  } while(val!=0);

  return ERR_OK;

}

 

uint8_t SOCK_Disconnect(uint8_t sock) {

  uint8_t val;

  uint16_t sockaddr;

 

  if (sock>=W5100_NUM_SOCKETS) {

    return ERR_VALUE;

  }

  sockaddr = W5100_SKT_BASE(sock);

  /* Send Disconnect Command */

  W5100_MemWriteByte(sockaddr+W5100_CR_OFFSET, W5100_CR_DISCON);

  do { /* Wait for Disconnecting Process */

    W5100_MemReadByte(sockaddr+W5100_CR_OFFSET, &val);

  } while(val!=0);

  return ERR_OK;

}

 

uint8_t SOCK_OpenSocket(uint8_t sock, uint8_t eth_protocol, uint16_t tcp_port) {

  uint8_t val;

  uint16_t sockaddr;

 

  if (sock>=W5100_NUM_SOCKETS) {

    return ERR_VALUE; /* out of range */

  }

  sockaddr =  W5100_SKT_BASE(sock);

  /* Make sure we close the socket first */

  if (W5100_MemReadByte(sockaddr+W5100_SR_OFFSET, &val)!=ERR_OK) {

    return ERR_FAILED; /* failure */

  }

  if (val==W5100_SOCK_CLOSED) {

    /* make sure we close the socket */

    SOCK_CloseSocket(sock);

  }

  /* Assigned Socket 0 Mode Register */

  W5100_MemWriteByte(sockaddr+W5100_MR_OFFSET, eth_protocol);

  /* Now open the Socket 0 */

  W5100_MemWriteWord(sockaddr+W5100_PORT_OFFSET, tcp_port);

  W5100_MemWriteByte(sockaddr+W5100_CR_OFFSET, W5100_CR_OPEN);  /* Open Socket */

  /* Wait for Opening Process */

  do {

    W5100_MemReadByte(sockaddr+W5100_CR_OFFSET, &val);

  } while(val!=0);

  /* Check for Init Status */

  W5100_MemReadByte(sockaddr+W5100_SR_OFFSET, &val);

  if (val==W5100_SOCK_INIT) {

    return ERR_OK;

  } else {

    SOCK_CloseSocket(sock);

  }

  return ERR_FAILED;

}

 

uint8_t SOCK_Listen(uint8_t sock) {

  uint8_t val;

  uint16_t sockaddr;

 

  if (sock>=W5100_NUM_SOCKETS) {

    return ERR_VALUE;

  }

  sockaddr = W5100_SKT_BASE(sock);

  W5100_MemReadByte(sockaddr+W5100_SR_OFFSET, &val);

  if (val==W5100_SOCK_INIT) {

    /* Send the LISTEN Command */

    W5100_MemWriteByte(sockaddr+W5100_CR_OFFSET, W5100_CR_LISTEN);

    /* Wait for Listening Process */

    do {

      W5100_MemReadByte(sockaddr+W5100_CR_OFFSET, &val);

    } while(val!=0);

    /* Check for Listen Status */

    W5100_MemReadByte(sockaddr+W5100_SR_OFFSET, &val);

    if (val==W5100_SOCK_LISTEN) {

      return ERR_OK;

    } else {

      SOCK_CloseSocket(sock);

    }

  }

  return ERR_FAILED;

}

 

uint8_t SOCK_Send(uint8_t sock, const uint8_t *buf, size_t buflen) {

  uint16_t offaddr, realaddr, txsize, timeout, sockaddr;

  uint8_t val;

 

  if (buflen<=0 || sock>=W5100_NUM_SOCKETS) {

    return ERR_VALUE;

  }

  sockaddr = W5100_SKT_BASE(sock);

  /* Make sure the TX Free Size Register is available */

  W5100_MemReadWord(sockaddr+W5100_TX_FSR_OFFSET, &txsize);

  timeout=0;

  while (txsize<buflen) {="" wait1_waitosms(1);="" w5100_memreadword(sockaddr+w5100_tx_fsr_offset,="" &<span="" class="hiddenSpellError" pre="">txsize);    /* Timeout for approximately 1000 ms */    if (timeout++ > 1000) {

     /* Disconnect the connection */

     SOCK_Disconnect(sock);

     return ERR_FAILED;

    }

  }

  /* Read the Tx Write Pointer */

  W5100_MemReadWord(sockaddr+W5100_TX_WR_OFFSET, &offaddr);

  while(buflen) {

    buflen--;

    /* Calculate the real W5100 physical Tx Buffer Address */

    realaddr = (W5100_TXBUFADDR+(0x0800*sock)) + (offaddr&W5100_TX_BUF_MASK);

    /* Copy the application data to the W5100 Tx Buffer */

    W5100_MemWriteByte(realaddr, *buf);

    offaddr++;

    buf++;

  }

  /* Increase the S0_TX_WR value, so it point to the next transmit */

  W5100_MemWriteWord(sockaddr+W5100_TX_WR_OFFSET, offaddr);

  /* Now Send the SEND command */

  W5100_MemWriteByte(sockaddr+W5100_CR_OFFSET, W5100_CR_SEND);

  /* Wait for Sending Process */

  do {

    W5100_MemReadByte(sockaddr+W5100_CR_OFFSET, &val);

  } while(val!=0);

  return ERR_OK;

}

 

uint8_t SOCK_Receive(uint8_t sock, uint8_t *buf, size_t bufSize, size_t readSize) {

  uint16_t offaddr, realaddr;

  uint16_t sockaddr;

 

  if (readSize<=0 || sock>=W5100_NUM_SOCKETS) {

    return ERR_VALUE; /* failure */

  }

  if (readSize>bufSize) { /* If the requested size > MAX_BUF, just truncate it */

    readSize = bufSize-2;

  }

  sockaddr = W5100_SKT_BASE(sock);

  /* Read the Rx Read Pointer */

  W5100_MemReadWord(sockaddr+W5100_RX_RD_OFFSET, &offaddr);

  while (readSize) {

    readSize--;

    realaddr = (W5100_RXBUFADDR + (0x0800*sock))+(offaddr&W5100_RX_BUF_MASK);

    W5100_MemReadByte(realaddr, buf);

    offaddr++;

    buf++;

  }

  *buf='\0';  /* string terminated character */

  /* Increase the S0_RX_RD value, so it point to the next receive */

  W5100_MemWriteWord(sockaddr+W5100_RX_RD_OFFSET, offaddr);

  /* Now Send the RECV command */

  W5100_MemWriteByte(sockaddr+W5100_CR_OFFSET, W5100_CR_RECV);

  WAIT1_Waitus(5);    /* Wait for Receive Process */

  return ERR_OK;

}

 

uint8_t SOCK_ReceivedSize(uint8_t sock, uint16_t *rxSize) {

  uint16_t sockaddr;

  *rxSize = 0;

  if (sock>=W5100_NUM_SOCKETS)  {

    return ERR_VALUE;

  }

  sockaddr = W5100_SKT_BASE(sock); // calc base addr for this socket

  return W5100_MemReadWord(sockaddr+W5100_RX_RSR_OFFSET, rxSize);

}

 

uint8_t SOCK_GetStatus(uint8_t sock, uint8_t *status) {

  uint16_t sockaddr;

 

  if (sock>=W5100_NUM_SOCKETS)  {

    return ERR_VALUE;

  }

  sockaddr = W5100_SKT_BASE(sock);

  return W5100_MemReadByte(sockaddr+W5100_SR_OFFSET, status);

}

 

void SOCK_Deinit(void){

  /* nothing needed */

}

 

void SOCK_Init(void) {

  /* nothing needed */

}

Web Server

The web server ‘task’ gets called from the application main loop:

  1. It gets the status from the socket: If the socket is closed, it opens the socket with TCP protocol on the HTTP port (80), and then listens to the socket.
  2. Once a communication connection is established, it checks how many bytes has been received and reads them into a buffer. If there is data, it inspects the data.

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

   void SERVER_Process(uint8_t socket) {

    uint8_t status;

  uint16_t rsize;

 

  if (SOCK_GetStatus(socket, &status)!=ERR_OK) {

    return; /* failed */

  }

  switch (status) {  /* based on current status of socket... */

    case W5100_SOCK_CLOSED:  /* socket closed */

      if (SOCK_OpenSocket(socket, W5100_SKT_MR_TCP, SERVER_HTTP_PORT)==ERR_OK) {

        /* successful opened the socket */

        (void)SOCK_Listen(socket);

      }

      break;

    case W5100_SOCK_ESTABLISHED:

      (void)SOCK_ReceivedSize(socket, &rsize); /* how many bytes received? */

      if (rsize>0) { /* received data */

        if (SOCK_Receive(socket, buf, sizeof(buf), rsize)!=ERR_OK)  {

          break; /* something failed, get out here */

        }

        /* check the content */

        CheckData(socket, buf, sizeof(buf), rsize);

      }

      break;

 

    case W5100_SOCK_INIT:

      break;

 

    case W5100_SOCK_FIN_WAIT:

    case W5100_SOCK_CLOSING:

    case W5100_SOCK_TIME_WAIT:

    case W5100_SOCK_CLOSE_WAIT:

    case W5100_SOCK_LAST_ACK:

      SOCK_CloseSocket(socket);

      break;

  } /* switch */

}

Communication between Client and Server

To display a page from our web server in a client (a web browser, such as FireFox), the following happens:

  1. Enter the address of the board in the browser (e.g. http://192.168.0.12)
  2. The browser connects to the socket I have created with SOCK_OpenSocket() and which is listening to the incoming requests with SOCK_Listen(). By default it uses the standard TCP/IP port 80 (standard HTTP server port).
  3. In the server, I get a W5100_SOCK_ESTABLISHED status.
  4. The browser sends an HTTP “GET“or “POST” request to the server. With SOCK_ReceivedSize() the server knows the size of the request, and withSOCK_Receive() the server can get the data from the socket.

GET Request

The client is sending a GET request to retrieve the HTML text to display.


                              image

                      

                                                                                  HTTP GET Request

 

A GET is sent as well if I do a refresh in the web browser. The text of the GET request is what I get from the socket using SOCK_Receive(), and looks like this, with a “GET /” at the beginning:

GET / HTTP/1.1 Host: 192.168.0.80 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Connection: keep-alive

The web server responds to this with the HTML code. And this is done in my server implementation with this function SendPage().

:!: Because that source code contains HTML code, WordPress was not able to properly show the source code here. Have look in the Server.c on GitHub.

This constructs the HTML code for my page, which then looks like this:

                                 Web Server with W5100 on FRDM-KL25Z

                                                                   Web Server with W5100 on FRDM-KL25Z

At the end, it performs a disconnect of the socket so other clients can connect to that socket.

POST Request

A POST request is sent by the client for that ‘Submit Query’ button: it will send me the state of the radio buttons so I can turn the red LED on or off.

                               HTTP Post

                                                                                               HTTP Post

Such a POST message looks like this:

POST / HTTP/1.1 Host: 192.168.0.80 User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:26.0) Gecko/20100101 Firefox/26.0 Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 Accept-Language: de-de,de;q=0.8,en-us;q=0.5,en;q=0.3 Accept-Encoding: gzip, deflate Referer: http://192.168.0.80/ Connection: keep-alive Content-Type: application/x-www-form-urlencoded Content-Length: 7  radio=0

Depending on which radio button is selected, there is “radio=0″ or “radio=1″ in the message. So for such a POST message, the web server needs to

  1. Detect that it is a POST message (this is known by the “POST /” at the beginning)
  2. Find the “radio=” in the message.

strFind()

To find such substrings in the message, I have implemented a simple ‘search substring inside a string and return the position’. This function I have put into my utility component:

1

2

3

4

5

6

7

8

9

10

11

12

  int16_t UTIL1_strFind(byte *str, byte *subStr)

  {

  int i, len;

 

  len = UTIL1_strlen((char*)subStr);

  for (i=0; *str!='\0'; i++, str++) {

    if (UTIL1_strncmp((char*)str, (char*)subStr, len)==0) {

      return i; /* found */

    }

  }

  return -1; /* not found */

}

Checkin the HTML Data from the Client

The last piece of the server is the function to find the “GET” and “POST” messages, and then to send the result back to the client:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

  static void CheckData(uint8_t socket, uint8_t *buf, size_t bufSize, uint16_t rsize) {

  int getidx, postidx;

 

#if 1 /* debug output */

  CLS1_SendStr((uint8_t*)"\r\n-------------------------\r\n", CLS1_GetStdio()->stdOut);

  CLS1_SendStr(buf, CLS1_GetStdio()->stdOut);

  CLS1_SendStr((uint8_t*)"\r\n-------------------------\r\n", CLS1_GetStdio()->stdOut);

#endif

  getidx = UTIL1_strFind(buf, (unsigned char*)"GET /");

  postidx = UTIL1_strFind(buf, (unsigned char*)"POST /");

  if (getidx >= 0 || postidx >= 0) {

    /* check the Radio Button for POST request */

    if (postidx>=0) {

      if (UTIL1_strFind(buf, (unsigned char*)"radio=0")>0) {

        LED1_Off();

      }

      if (UTIL1_strFind(buf, (unsigned char*)"radio=1")>0) {

        LED1_On();

      }

    }

    SendPage(socket, 23, LED1_Get());

  }

}

For debugging purposes I print the received message to the console.

Putting everything together

Oh, one thing is missing: how to call the server processing function. I do this in my application inside a FreeRTOS task, but that can be done easily without an RTOS too:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

static portTASK_FUNCTION(Task1, pvParameters) {

  (void)pvParameters; /* parameter not used */

  WiznetSetup();

  CLS1_SendStr((unsigned char*)"Running web server...\r\n", CLS1_GetStdio()->stdOut);

  for(;;) {

    SERVER_Process(0);

    FRTOS1_vTaskDelay(50/portTICK_RATE_MS);

  }

}

 

void APP_Run(void) {

  cardMounted = FALSE;

  SHELL_Init();

  W5100_Init();

  SOCK_Init();

  SERVER_Init();

  if (FRTOS1_xTaskCreate(

    Task1,  /* pointer to the task */

    (signed char *)"Task1", /* task name for kernel awareness debugging */

    configMINIMAL_STACK_SIZE+100, /* task stack size */

    (void*)NULL, /* optional task startup argument */

    tskIDLE_PRIORITY,  /* initial priority */

    (xTaskHandle*)NULL /* optional task handle to create */

  ) != pdPASS) {

    /*lint -e527 */

    for(;;){}; /* error! probably out of memory */

    /*lint +e527 */

   }

  FRTOS1_vTaskStartScheduler();

}

With this I have a functional web server on my FRDM-KL25Z board. I can use it to give status, but with the POST commands I can do actions (e.g. turning on or off an LED, etc).

Summary

The combination of the Arduino Ethernet Shield with the FRDM-KL25Z makes a web server implementation very easy. With this, I can use and control the board through the network, a first and simple step into the IoT (Internet of Things)

The current project is available on GitHub here.

Other ideas for a continuation of this series:

  • Having the HTML pages with Java scripts and images on the SD card
  • Adding easier network integration, like using DHCP instead of static IP addresses

 

Happy Webingimage

  • Share
  • History
  • More
  • Cancel
  • Sign in to reply
element14 Community

element14 is the first online community specifically for engineers. Connect with your peers and get expert answers to your questions.

  • Members
  • Learn
  • Technologies
  • Challenges & Projects
  • Products
  • Store
  • About Us
  • Feedback & Support
  • FAQs
  • Terms of Use
  • Privacy Policy
  • Legal and Copyright Notices
  • Sitemap
  • Cookies

An Avnet Company © 2025 Premier Farnell Limited. All Rights Reserved.

Premier Farnell Ltd, registered in England and Wales (no 00876412), registered office: Farnell House, Forge Lane, Leeds LS12 2NE.

ICP 备案号 10220084.

Follow element14

  • X
  • Facebook
  • linkedin
  • YouTube