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 2: Ping
  • 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 7:53 AM Date Created
  • Last Updated Last Updated: 18 Mar 2014 1:27 PM
  • Views 563 views
  • Likes 0 likes
  • Comments 0 comments
Related
Recommended

Interfacing FRDM-KL25Z with Arduino Ethernet Shield R3 on Processor Expert, Part 2: Ping

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

In Part 1 of this series I have covered the SD card on the Arduino Ethernet shield. In Part 2 I’m hooking up the board to the network and will be able to ping it.

               Arduino Ethernet Shield with FRDM-KL25Z

                                                  Arduino Ethernet Shield with 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

Hardware

The W5100 has a TCP/IP stack built into the hardware, which makes it easy to use with any small microcontroller, including the Freescale KL25Z on the FRDM-KL25ZFRDM-KL25Z board. TheArduino Ethernet Shield R3Arduino Ethernet Shield R3 I’m using requires a hardware change to map the SPI signals to the Arduino header: See Part 1 of this series.

SPI Communication

The W5100 uses the ‘Mode 0′ SPI protocol:

  1. Clock Idle polarity low
  2. Data shifted on rising edge

After activivating the CS (Chip Select, LOW active) line, a command byte (0xF0 for write, 0x0F for read) is sent, followed by the address (16bit, most significant byte first), and then the data byte. Within a byte, the MSB (Most Significant Bit) is sent first.

Write

The screenshot below shows the write command 0xF0 which writes the value 0xC0 to address 0×0001:

               W5100 SPI Write Byte

                                                                            W5100 SPI Write Byte

So a transaction is always 32 bits: 1 command byte, 2 address bytes, one data byte. As you can see, the W5100 responds on the MISO line with increasing values to the write command.

Read

Reading from the device is very similar. For this the command 0x0F is used. Below is the read operation which reads back the value from address 0×0001:

               W5100 SPI Read Byte

                                                                          W5100 SPI Read Byte

Chip Select

The chip select for the W5100 is low active, and to abstract from the hardware, I’m using defines:

 

1

      2

#define W5100_CS_ENABLE()   ETH_CS_ClrVal()

#define W5100_CS_DISABLE()  ETH_CS_SetVal()

 

 

Semaphore

As the SPI bus is shared between the SD card and W5100, I’m using a semaphore to grant mutual access to the bus:

      1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

  static xSemaphoreHandle SPImutex = NULL; /* Semaphore to protect SPI access */

 

  void W5100_RequestSPIBus(void) {

  (void)xSemaphoreTakeRecursive(SPImutex, portMAX_DELAY);

}

 

void W5100_ReleaseSPIBus(void) {

  (void)xSemaphoreGiveRecursive(SPImutex);

}

 

void W5100_GetBus(void) {

  W5100_RequestSPIBus();

  W5100_CS_ENABLE();

}

 

void W5100_ReleaseBus(void) {

  W5100_CS_DISABLE();

  W5100_ReleaseSPIBus();

}

SPI Read and Write

Using the Processor Expert SPI component, dealing with the SPI protocol gets really simple. I need to catch the hook for the finished SPI transaction and wait until the transaction is finished:

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

  static volatile bool W5100_DataReceivedFlag = FALSE;

 

  void W5100_OnBlockReceived(LDD_TUserData *UserDataPtr) {

  (void)UserDataPtr;

  W5100_DataReceivedFlag = TRUE;

}

 

static void SPIWriteByte(unsigned char write) {

  unsigned char dummy;

 

  W5100_DataReceivedFlag = FALSE;

  (void)SM1_ReceiveBlock(SM1_DeviceData, &dummy, sizeof(dummy));

  (void)SM1_SendBlock(SM1_DeviceData, &write, sizeof(write));

  while(!W5100_DataReceivedFlag){}

}

 

static uint8_t SPIReadByte(void) {

  uint8_t val, write = 0xff; /* dummy */

 

  W5100_DataReceivedFlag = FALSE;

  (void)SM1_ReceiveBlock(SM1_DeviceData, &val, 1);

  (void)SM1_SendBlock(SM1_DeviceData, &write, 1);

  while(!W5100_DataReceivedFlag){}

  return val;

}

:!: This code polls for the DataReceivedFlag. To make the code more robust, a timeout should be used. I keep things simple here.

Read/Write Registers

To read and write the W5100 registers, this can be done like this:

 

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

    19

  uint8_t W5100_MemWriteByte(uint16_t addr, uint8_t val) {

  W5100_GetBus();

  SPIWriteByte(W5100_CMD_WRITE);

  SPIWriteByte(addr>>8); /* high address */

  SPIWriteByte(addr&0xff); /* low address */

  SPIWriteByte(val); /* data */

  W5100_ReleaseBus();

  return ERR_OK;

}

 

uint8_t W5100_MemReadByte(uint16_t addr, uint8_t *val) {

  W5100_GetBus();

  SPIWriteByte(W5100_CMD_READ);

  SPIWriteByte(addr>>8); /* high address */

  SPIWriteByte(addr&0xff); /* low address */

  *val = SPIReadByte(); /* data */

  W5100_ReleaseBus();

  return ERR_OK;

}

Read/Write Multiple Bytes

To read or write more than one byte, the single byte read/write routines are used:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

   19

  uint8_t W5100_MemReadBlock(uint16_t addr, void *data, size_t dataSize) {

  while(dataSize>0) {

    if (W5100_MemReadByte(addr, (uint8_t*)data)!=ERR_OK) {

      return ERR_FAILED;

    }

    data++; addr++; dataSize--;

  }

  return ERR_OK;

}

 

uint8_t W5100_MemWriteBlock(uint16_t addr, void *data, size_t dataSize) {

  while(dataSize>0) {

    if (W5100_MemWriteByte(addr, *((uint8_t*)data))!=ERR_OK) {

      return ERR_FAILED;

    }

    data++; addr++; dataSize--;

  }

  return ERR_OK;

}

 

An example to read/write multiple bytes is for the network configuration:

1

2

3

4

5

6

7

8

9

10

11

12

13

   14

typedef struct w5100_config {

  uint8_t gateway[4]; /* gateway address, e.g. 192.168.0.1 */

  uint8_t netmask[4]; /* network mask, e.g. 255.255.255.0 */

  uint8_t hwaddr[6]; /* hardware MAC address, e.g. 90:a2:da:0D:42:dd */

  uint8_t ipaddr[4]; /* own IP address, e.g. 192.168.0.90 */

} w5100_config_t;

 

uint8_t W5100_WriteConfig(w5100_config_t *config) {

  return W5100_MemWriteBlock(W5100_GAR0, (void*)config, sizeof(w5100_config_t));

}

 

uint8_t W5100_ReadConfig(w5100_config_t *config) {

  return W5100_MemReadBlock(W5100_GAR0, (void*)config, sizeof(w5100_config_t));

}

I will cover this more later.

Application Initialization

With this, we are ready to configure the W5100.

Mode Register

The W5100 has the MR (Mode Register) register with the following bits:

1

2

3

4

5

   6

  #define W5100_MR    0x00 /* MR (Mode Register */

  #define W5100_MR_BIT_IND    (1<<0) /* indirect bus interface mode */

#define W5100_MR_BIT_AI     (1<<1) /* address auto-increment in indirect bus interface, 1 to enable */

#define W5100_MR_BIT_PPPoE  (1<<3) /* PPPoE mode, 1 to enable */

#define W5100_MR_BIT_PB     (1<<4) /* ping block bit, 1 to block pings */

#define W5100_MR_BIT_RST    (1<<7) /* reset bit, 1 to reset internal registers */

Of interest is the RST (Reset) bit. Setting it to one will reset the device:

1

2

3

4

   5

  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);

}

Network Address

Next, I need to configure the network address information. For this I need to configure the gateway, the network mask, IP address and the MAC (Hardware Address). The MAC address I can find on the sticker of my Ethernet Shield:

                    Ethernet Shield MAC Address

                              Ethernet Shield MAC Address

With this, I set up my network configuration like this:

1

2

3

4

5

   6

  static const w5100_config_t W5100_config = {

    {192, 168, 1, 1}, /* gateway */

  {255, 255, 255, 0}, /* netmask */

  {0x90, 0xa2, 0xda,0x0D, 0x42, 0xdd}, /* hw/mac address */

  {192, 168, 0, 80} /* ip address */

};

And configure it:

1

2

3

4

   5

  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);

}

RX/TX Memory Buffer

The W5100 can deal with up to 4 network sockets, with a total of 2×8 KByte for RX (RMSR register) and TX (TMSR register) buffers. Default is to use 2 KByte for each socket:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

   20

  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);

}

:idea: There are other things to configure like number of retry, but I keep them on the default values for now.

Status Output

I have added a command line shell interface to the W5100 driver, so I can inspect my network configuration:

              Status Network Configuration

                                         Status Network Configuration

Ping

Finally, time to see if the W5100 responds on ping commands. For this I ‘ping’ the IP address I have assigned:

               Ping my Board

                                                                           Ping my Board

Congratulations!

:idea: If pinging does not work: check the network address and network setup. If the W5100_MR_BIT_PB bit is set in the W5100_MR register, then the W5100 does *not* respond to pings!

Summary

I have now the FRDM-KL25Z hooked up to the network with the Arduino Ethernet shield. It does not much for now, it only responds to pings, but this is a good starter image. The software project is available on GitHub.
            github

:idea: I recommend to have a look this very good blog post by rwb.

Happy Pingingimage

  • 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