Wiznet makers

scott

Published September 30, 2022 ©

76 UCC

18 WCC

36 VAR

0 Contests

0 Followers

0 Following

Original Link

Nucleo-F401RE + Ethernet(W5100) + MicroPythonでインターネット接続

This project utilizes Nucleo-F401RE + W5100 based on MicroPython.

COMPONENTS Hardware components

WIZnet - W5100

x 1


x 1


PROJECT DESCRIPTION

Nucleo-F401RE with MicroPython started to work, but there is no internet connection compared to ESP32.
However, after some research, I found that this board can be connected to an Ethernet shield for Arduino.

Adding ethernet connectivity to a STM32-Nucleo

Actually, I also have an Ethernet shield for Arduino that I bought but haven't used (this pattern is common), and it uses the same chip called W5100 as the above article.

This chip is a product of a manufacturer called WIZnet, and it is not just an Ethernet controller, it has TCP/IP implemented and can communicate on its own.
Is it something like a LAN version of ESP8266 as an image?
It is a series that has been around for a long time than ESP8266, and it is switch science in Japan.It is handled by Mr.

On the other hand, when I researched MicroPython, I found that this W5000 series can be incorporated as a driver.
However, only the W5200 and W5500 were supported at this time.

Ethernet Adapter for PyBoard Which? – MicroPython Forum

The combination of W5500 and STM32 seems to have been bug-fixed very recently.

drivers: WIP getting WizNet5500 working with stm32 port. by dpgeorge · Pull Request #3362 · micropython/micropython

Unfortunately, MicroPython did not include the W5100 driver, but when I checked the W5200 and W5500 drivers, they used the drivers developed by WIZnet.
So, when I looked into WIZnet's GitHub, I found that the W5100 driver was also prepared.
There is also an abstraction layer that absorbs the differences between these chips, and MicroPython seems to use it as well.

So, I thought it would be easy to port the WIZnet W5100 driver to MicroPython, so I decided to give it a try.

The WIZnet driver used is this library, which seems to be the latest version at the moment.

Wiznet/ioLibrary_Driver: Create a repository of WIZnet ioLibrary.

There is an "Ethernet" folder that contains drivers and an "Internet" folder that implements protocols such as DNS, but I used only the Ethernet folder.
It seems that MicroPython uses the DNS implementation of the Internet folder, so at first I thought I should use the latest one, but the latest one gives a compilation error (or rather, there are still bugs). so i stopped using it.

Extract this Ethernet folder to micropython/drivers/wiznet5k/Ethernet.
Then, change the specification of the chip to be used as follows.

../../ioLibrary_Driver/Ethernet/wizchip_conf.h wizchip_conf.h
64c64
< #define _WIZCHIP_                      5500   // 5100, 5200, 5300, 5500
---
> #define _WIZCHIP_                      5100   // 5100, 5200, 5300, 5500

Also, wizchip_conf.c, which is the abstraction layer of the driver, has a syntax error at the time of structure initialization, so we will fix it.

../../ioLibrary_Driver/Ethernet/wizchip_conf.c wizchip_conf.c
169,172c169,172
<       wizchip_cris_enter,
<       wizchip_cris_exit,
<       wizchip_cs_select,
<       wizchip_cs_deselect,
---
>       {wizchip_cris_enter,
>        wizchip_cris_exit},
>       {wizchip_cs_select,
>        wizchip_cs_deselect},
176,177c176,177
<       wizchip_bus_readdata,
<       wizchip_bus_writedata,
---
>       {{wizchip_bus_readdata,
> 	wizchip_bus_writedata}},

The WIZnet chip implements a socket interface.
Well-known APIs such as connect and listen are used for the function names, but following the ones originally built into MicroPython, we introduced macros to change the names of socket-related functions.

../../ioLibrary_Driver/Ethernet/socket.h socket.h
87a88,90
> // use this macro for exported names to avoid name clashes
> #define WIZCHIP_EXPORT(name) wizchip_ ## name
>
162c165
< int8_t  socket(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag);
---
> int8_t  WIZCHIP_EXPORT(socket)(uint8_t sn, uint8_t protocol, uint16_t port, uint8_t flag);

Although omitted below, the above changes are made to all function names socket, close, listen, connect, disconnect, send, recv, sendto, recvfrom, ctlsocket, setsockopt, getsockopt.
Also make similar changes to socket.c.
In addition to the declaration part of the function, there is a place where close() is called internally, so it is necessary to change there as well.

Also, an error occurred during compilation due to the use of the & operator, so I fixed the following.

520,521c520,521
<    if((taddr == 0) && (getSn_MR(sn)&Sn_MR_MACRAW != Sn_MR_MACRAW)) return SOCKERR_IPINVALID;
<    if((port  == 0) && (getSn_MR(sn)&Sn_MR_MACRAW != Sn_MR_MACRAW)) return SOCKERR_PORTZERO;
---
>       if((taddr == 0) && ((getSn_MR(sn)&Sn_MR_MACRAW) != Sn_MR_MACRAW)) return SOCKERR_IPINVALID;
>       if((port  == 0) && ((getSn_MR(sn)&Sn_MR_MACRAW) != Sn_MR_MACRAW)) return SOCKERR_PORTZERO;

The W5100 driver does not need to be changed at all. However, I will modify w5100.h a little for the convenience of the include path.

../../../../../ioLibrary_Driver/Ethernet/W5100/w5100.h w5100.h
44c44
< #include "wizchip_conf.h"
---
> #include "../wizchip_conf.h"

Also, modify only one line in dns.h in the application/dns/ folder.

diff dns.c dns.c~
57c57
< #include "../../Ethernet/socket.h"
---
> #include "../../ethernet/socket.h"

I will write a little about the internal structure of MicroPython here.
STM32 related implementations are collected in "ports/stm32".
The network module is implemented in modnetwork.c, but implementations for different types of NICs are in separate files.
The implementation for the WIZnet5K series is in modnwwiznet5k.c, and this implementation uses SPI via the STM32 HAL library to communicate with WIZnet5K devices.

The API of the WIZnet5K drivers has changed slightly from what was originally included in MicroPython, so we also had to modify the modnwwiznet5k.c side that calls these drivers.
Specifically, we added a new SPI callback function that sends and receives one byte at a time.
Also, the W5000 series register names have changed slightly.

diff modnwwiznet5k.c modnwwiznet5k.c.org
41,42c41,42
< #include "Ethernet/wizchip_conf.h"
< #include "Ethernet/socket.h"
---
> #include "ethernet/wizchip_conf.h"
> #include "ethernet/socket.h"
74,87c74
< STATIC uint8_t wiz_spi_read(void) {
<   uint8_t c;
<     HAL_StatusTypeDef status = HAL_SPI_Receive(wiznet5k_obj.spi, &c, 1, 5000);
<     (void)status;
<     return c;
< }
<
< STATIC void wiz_spi_write(uint8_t c) {
<     HAL_StatusTypeDef status = HAL_SPI_Transmit(wiznet5k_obj.spi, &c, 1, 5000);
<     (void)status;
< }
<
< //STATIC void wiz_spi_read(uint8_t *buf, uint32_t len) {
< STATIC void wiz_spiburst_read(uint8_t *buf, uint16_t len) {
---
> STATIC void wiz_spi_read(uint8_t *buf, uint32_t len) {
92,93c79
< //STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) {
< STATIC void wiz_spiburst_write(uint8_t *buf, uint16_t len) {
---
> STATIC void wiz_spi_write(const uint8_t *buf, uint32_t len) {
381d366
<     reg_wizchip_spiburst_cbfunc(wiz_spiburst_read, wiz_spiburst_write);
424c409
<             printf(" %02x", WIZCHIP_READ(WIZCHIP_OFFSET_INC(WIZCHIP_SREG_BLOCK(sn), i)));
---
>             printf(" %02x", WIZCHIP_READ(WIZCHIP_SREG_ADDR(sn, i)));

Lastly is the Makefile.
Since this was also specified as W5200, I will correct that and the include path.

diff Makefile Makefile.org
295,297c295,297
< 	Ethernet/W5100/w5100.c \
< 	Ethernet/wizchip_conf.c \
< 	Ethernet/socket.c \
---
> 	ethernet/w5200/w5200.c \
> 	ethernet/wizchip_conf.c \
> 	ethernet/socket.c \

The porting process is now complete.
make

cd  micropython/ports/stm32/ 
make  BOARD=NUCLEO_F401RE CROSS_COMPILE=~/gcc-arm-none-eabi-5_4-2016q3/bin/arm-none-eabi-MICROPY_PY_WIZNET5K=1 
cd  build-NUCLEO_F401RE/ 
cp  firmware.hex /mnt/ hgfs/share/ 
# Write with ST-Link Utility after this

I actually accessed the Internet with Nucleo-F401RE and W5100.
The connection is as shown below.

stm32-w5100.png

Adding ethernet connectivity to a STM32-Nucleo As written in , this Ethernet shield outputs SPI signals to a 6-pin terminal that the Nucleo board does not have, so it is necessary to devise wiring.
On my board, the wire was exposed at the foot of the 6-pin terminal, so I used an IC clip to connect it.

ethernet-shield-spi.jpg

First of all, when using ESP32 As with, try to connect to ASCII art STAR WARS.
If the SPI object is machine.SPI, I get an error that the class is different, so I had to use pyb.SPI.
I think this is a MicroPython problem.

 

 

def main():

 

import network, socket

 

from machine import Pin

 nic = network.WIZNET5K(pyb.SPI(2), Pin('PB12'), Pin('PC8'))
 addr = socket.getaddrinfo('towel.blinkenlights.nl', 23)[0][-1]
 s = socket.socket()
 s.connect(addr)
 

while True:

 data = s.recv(1500)
 

print(data.decode('utf-8'), end='')

view raww5100test1.py hosted with ❤ by GitHub

 

It was a little jerky, but it was displayed for the time being.

starwars.png

According to the article below, the communication speed of the W5k series seems to be 4.4 Mbps when using DMA with the latest W5500, and about 1.7 Mbps when not using it.

Using SPI DMA with STM32F401RE to improve transmission and reception performance of W5500 | WIZnet JP Blog

I also tried to communicate with HTTP.
When this is ESP32 againIt's the same story.
This time, the LCD is not used, and it is a confirmation whether communication is possible for the time being.
WIZNET5K objects didn't implement readline(), so the code is slightly different.

 

 

def main():

 

import network, socket, ujson

 

from machine import Pin

 nic = network.WIZNET5K(pyb.SPI(2), Pin('PB12'), Pin('PC8'))
 addr = socket.getaddrinfo('api.fixer.io',80)[0][-1]
 s = socket.socket()
 s.connect(addr)
 s.send(bytes('GET /latest?base=USD&symbols=JPY HTTP/1.0\r\nHost: api.fixer.io\r\n\r\n', 'utf8'))
 result = s.recv(1000)
 s.close()
 lines = result.splitlines()
 pos = lines.index(b'')
 parsed = ujson.loads(lines[pos + 1])
 

print(parsed["date"])

 

print("JPY/" + parsed["base"] + ": " + str(parsed["rates"]["JPY"]))

view raww5100test2.py hosted with ❤ by GitHub

 

Call it in the REPL to see the results.

>>> main()
2017-10-13
JPY/USD: 112.18
>>> 
Documents
Comments Write