Arduino_core_stm32: UIPEthernet library - doesnt work

Created on 16 Oct 2017  路  28Comments  路  Source: stm32duino/Arduino_Core_STM32

i've got this kind of error

../Enc28J60Network.h:106:5: error: #error "Not defined ENC28J60_CONTROL_CS!"
../Enc28J60Network.h:131:5: error: #error "Not defined SPI_MOSI!"
../Enc28J60Network.h:156:5: error: #error "Not defined SPI_MISO!"
../Enc28J60Network.h:180:5: error: #error "Not defined SPI_SCK!"

with default examples

Help wanted Question Third party Library

Most helpful comment

Hi guys,

I've submitted the support of this core to the UIPEthernet repo with a proper fix for the endianness issue I think.
https://github.com/UIPEthernet/UIPEthernet/pull/26

All 28 comments

Hi @valoni,

sounds normal as this library do not handle this core.
It seems it's should be easy to update by adding under ARDUINO_ARCH_STM32 the right pins assignment in Enc28J60Network.h using the default Arduino naming (SS, MOSI, MISO, SCK).

Could you try with this patch.
Build is ok but I do not make any test with a board.
STM32.patch.txt
If OK I will make a PR to the https://github.com/UIPEthernet/UIPEthernet

thanx, with this patch i can compile now .

so now i'm going to test it to see did work it

just a questions why this patch is needed to compile under STM32F411ret6 Nucleo which seems was already defined (but without this patch i can not compile with Nucleo board too)

In fact, Arduino_Core_STM32 core is a generic one for STM32 MCU. Only the ARDUINO_ARCH_STM32 is needed.
The other switches you've mentioned are for another STM32 core.

how to use for example switch for Nucle STM32F411RET6 without applying Patch !!!!

because without patch i've got errors as presented (if apply patch it compile)

../Enc28J60Network.h:106:5: error: #error "Not defined ENC28J60_CONTROL_CS!"
../Enc28J60Network.h:131:5: error: #error "Not defined SPI_MOSI!"
../Enc28J60Network.h:156:5: error: #error "Not defined SPI_MISO!"
../Enc28J60Network.h:180:5: error: #error "Not defined SPI_SCK!"

The TARGET_NUCLEO_F411RE is for mbed so you can't use it for Arduino.
For this one, fo r example:
#if defined(STM32F3) //This is workaround for stm32duino STM32F3
it is for the @rogerclarkmelbourne core:
https://github.com/rogerclarkmelbourne/Arduino_STM32

It mentions stm32duino linked to stm32duino.com forum where several Arduino Core for STM32 are proposed.

ok i understand now so the patch is an univesal approach for STM32 MCU (F1,F2,F4,...)
so in independent way from mcu allow used in same way for all those ARDUINO_ARCH_STM32 (on this arch which are all Nucleo64 board that are appeared on Arduino IDE Menu - if i am not wrong)

Yes, this core (Arduino_Core_STM32) appears in the menu like this:
SelectBoard
SelectBoard

Note, this is old screenshot they are more boards available now.
See the Wiki: https://github.com/stm32duino/wiki/wiki/Getting-Started

@valoni ,
have you tested with the library patched with the hardware.
If it is ok I will made a PR.

i'm abrooad and today i will return at home
so this weekend i will test it with hardware and will inform about it

Ok. Thanks @valoni

i can compile after applying patch
but tests with two differents HARDWARE (two different Ethernet ENC28J60 and Nucleo STM32F411RET6) do not work and i post sample which i used too
(also i tested with default samples too but not work)

/* Web Server */

include

byte mac[] = {0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
byte ip[]={192, 168, 1, 177};
byte subnet[]={255, 255, 255, 0};
byte gateway[]={192, 168, 1, 1};
byte mydns[]={192, 168, 1, 1};

// (port 80 is default for HTTP):
EthernetServer server(80);

void setup() {
// Open serial communications and wait for port to open:
Serial.begin(9600);

// start the Ethernet connection and the server:
Ethernet.begin(mac, ip, mydns, gateway, subnet);

server.begin();
Serial.print("server is at ");
Serial.println(Ethernet.localIP());
}

void loop() {
// listen for incoming clients
EthernetClient client = server.available();
if (client) {
Serial.println("new client");
// an http request ends with a blank line
boolean currentLineIsBlank = true;
while (client.connected()) {
if (client.available()) {
char c = client.read();
Serial.write(c);
// if you've gotten to the end of the line (received a newline
// character) and the line is blank, the http request has ended,
// so you can send a reply
if (c == '\n' && currentLineIsBlank) {
// send a standard http response header
client.println("HTTP/1.1 200 OK");
client.println("Content-Type: text/html");
client.println("Connection: close"); // the connection will be closed after completion of the response
client.println("Refresh: 5"); // refresh the page automatically every 5 sec
client.println();
client.println("");
client.println("");
// output the value of each analog input pin
for (int analogChannel = 0; analogChannel < 6; analogChannel++) {
int sensorReading = analogRead(analogChannel);
client.print("analog input ");
client.print(analogChannel);
client.print(" is ");
client.print(sensorReading);
client.println("
");
}
client.println("");
break;
}
if (c == '\n') {
// you're starting a new line
currentLineIsBlank = true;
} else if (c != '\r') {
// you've gotten a character on the current line
currentLineIsBlank = false;
}
}
}
// give the web browser time to receive the data
delay(1);
// close the connection:
client.stop();
Serial.println("client disconnected");
}
}

when i see on serial monitor instead to give me ip = 192, 168, 1, 177
it show ip = 168.192.177.1 (what wrong there)
on Arduino it seems have some trouble with arrays
so
*i attached another code that work well with mbed online compiler *

define LED_PIN D7

const int OFF = 0;
const int ON = 1;

include "mbed.h"

include "UIPEthernet.h"

include "UIPServer.h"

include "UIPClient.h"

include "string"

using namespace std;

Serial pc(USBTX, USBRX);

// uIPEthernet is the name of a global instance of UIPEthernet.
UIPEthernet uIPEthernet(D11, D12, D13, D10); // mosi, miso, sck, cs
//UIPEthernet uIPEthernet(PA_7, PA_6, PA_5, PB_6); // mosi, miso, sck, cs

const uint8_t MY_MAC[6] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };

const uint8_t MY_IP[4] = { 192, 168, 1, 177 };
const uint8_t MY_SUBNET[4] = { 255, 255, 255, 0 };
const uint8_t MY_GATEWAY[4] = { 192, 168, 1, 1 };
const uint8_t MY_DNS[4] = { 192, 168, 1, 1 };

const uint16_t MY_PORT = 80; // for HTTP connection

EthernetServer myServer = EthernetServer(MY_PORT);

// In this example we are turning on/off LED1.
DigitalOut sw(LED_PIN); // Change LED_PIN to a pin of your choice.
float roomTemp = 21.8; // A temperature sensor output

// However, make sure that it does not collide with any of the SPI pins
// already used in the uIPEthernet(...) constructor above!
const string PASSWORD = "secret"; // change as you like
const string HTTP_OK = "HTTP/1.0 200 OK";
const string MOVED_PERM = "HTTP/1.0 301 Moved Permanently\r\nLocation: ";
const string UNAUTHORIZED = "HTTP/1.0 401 Unauthorized";
string httpHeader; // HTTP header
string httpContent; // HTTP content

int8_t analyseURL(string& url) {
if(url.substr(5, PASSWORD.size()) != PASSWORD)
return(-1);

uint8_t pos = 5 + PASSWORD.size();

if(url.substr(pos, 1) == " ")
    return(-2);

if(url.substr(pos++, 1) != "/")
    return(-1);

string  cmd(url.substr(pos, 5));

if(cmd == "?sw=0")
    return(OFF);

if(cmd == "?sw=1")
    return(ON);

return(-3);

}

string& movedPermanently(uint8_t flag)
{
if(flag == 1)
httpContent = "/" + PASSWORD + "/";
else
httpContent = "";

httpContent += "<h1>301 Moved Permanently</h1>\r\n";

return(httpContent);

}

string& showWebPage(uint8_t status) {
char roomTempStr[5];

//roomTemp = ds1820.read();
sprintf(roomTempStr, "%3.1f", roomTemp);

httpContent = "<h2><a href=\".\" title=\"Click to refresh the page\">Smart Home</a></h2>";
httpContent += "<pre>Temperature:\t" + string(roomTempStr) + "&deg;C\r\n</pre>";

if(status == ON) {
    httpContent += "<pre>\r\nHeating:\t<font color=#FF0000>On </font>";
    httpContent += " <a href=\"./?sw=0\"><button>Turn off</button></a>\r\n";
}
else {
    httpContent += "<pre>\r\nHeating:\t<font color=#999999>Off</font>";
    httpContent += " <a href=\"./?sw=1\"><button>Turn on</button></a>\r\n";
}

httpContent += "</pre>\r\n";
httpContent += "<hr>\r\n";
httpContent += "<pre>2017 ARMmbed</pre>";
return httpContent;

}

void sendHTTP(EthernetClient& client, string& header, string& content)
{
char content_length[5] = { };

header += "\r\nContent-Type: text/html\r\n";
header += "Content-Length: ";
sprintf(content_length, "%d", content.length());
header += string(content_length) + "\r\n";
header += "Pragma: no-cache\r\n";
header += "Connection: About to close\r\n";
header += "\r\n";

string  webpage = header + content;
client.write((uint8_t*)webpage.c_str(), webpage.length());

}

int main(void)
{
uIPEthernet.begin(MY_MAC, MY_IP, MY_DNS, MY_GATEWAY, MY_SUBNET);
IPAddress localIP = uIPEthernet.localIP();
pc.printf("Type %s secret/ into your web browser and hit ENTER\r\n", localIP.toString());

myServer.begin();
while(1) {
EthernetClient client = myServer.available();
if(client) {
size_t size = client.available();
if(size > 0) {
uint8_t* buf = (uint8_t)malloc(size);
size = client.read(buf, size);
string received((char
)buf);
free(buf);

            if(received.substr(0, 3) != "GET") {
                httpHeader = HTTP_OK;
                httpContent = "<h1>200 OK</h1>";
                sendHTTP(client, httpHeader, httpContent);
                continue;
            }

            if(received.substr(0, 6) == "GET / ") {
                httpHeader = HTTP_OK;
                httpContent = "<p>Usage: http://host_or_ip/password</p>\r\n";
                sendHTTP(client, httpHeader, httpContent);
                continue;
            }

            int cmd = analyseURL(received);

            if(cmd == -2) {
                // redirect to the right base url
                httpHeader = MOVED_PERM;
                sendHTTP(client, httpHeader, movedPermanently(1));
                continue;
            }

            if(cmd == -1) {
                httpHeader = UNAUTHORIZED;
                httpContent = "<h1>401 Unauthorized</h1>";
                sendHTTP(client, httpHeader, httpContent);
                continue;
            }

            if(cmd == ON) {
                sw = ON;    // turn the switch on
            }

            if(cmd == OFF) {
                sw = OFF;   // turn the switch off
            }

            httpHeader = HTTP_OK;
            sendHTTP(client, httpHeader, showWebPage(sw));
        }
    }
}

}

Hi @valoni
unfortunately I do not have this hardware.
For the wrong IP adress print have you check on your box the real IP address?
It seems the UIPEthernetClass::localIP() uses some conversion which maybe could cause display issue.
Probably some other update are required but without the hardware I could not investigate.

I set ip statically

On pc i set:
192.168.1.175 ip
255.255.255.0 sub
192.168.1.1 gtw
192.168.1.1 dns

On nucleo (see code attached above)
192.168.1.177
255.255.255.0
192.168.1.1
192.168.1.1

Tried to ping from pc (nothing) with arduino code
But i can ping with mbed code well

So for this reason i provided 2 different code for different platforms (which i tested with NucleoSTM32F411Ret6)

1.Arduino IDE (that not work)
2.mbed online compiler(that work pretty well)

I have tried the patch from @fpistm. It allows to build the library but it does not work.

@valoni was right to point the faulty IPAddress, there is an endianness issue, replacing LITTLE_ENDIAN by BIG_ENDIAN in the following line made the demo sketch EchoServer works:

https://github.com/UIPEthernet/UIPEthernet/blob/602a12fa317eae911482de89e648dcef608c047f/utility/uip-conf.h#L125

Note that according to the other ports, I have tried to change the SPI clock divider here:

https://github.com/UIPEthernet/UIPEthernet/blob/602a12fa317eae911482de89e648dcef608c047f/utility/Enc28J60Network.cpp#L144

But with the default value on a L476 board, it works and the ping is faster.

Hi @romainreignier ,

thanks for the feedback.
Sounds strange for the endianness. Mainly linked to the HTONS:
https://github.com/UIPEthernet/UIPEthernet/blob/4966ee06bc29d42749ca3a3dde5d39cbe9183e98/utility/uip.h#L1066

By default SPI use a default clk of 4MHz and defined automatically the best clock divider.
So depending of the clock divider you tried maybe it runs slowly than 4MHz depending of the clk freq of the SPI instance.

Yes exactly, it is the HTONS macro that made me change the endianness definition.
I have also found it weird because for the other ARM platforms, the endianness was not changed so I wondered if you have change anything in the Arduino toolchain to create that issue.

In fact the HTONS only do usual bit shifting so I do not know where the issue is.

Actually, the IP address seems the issue because even with the default settings, the MCU is communicating without issue with the ENC28J60 chip, I can see the traffic when I ping it using the logs on the serial port. But it does not respond because the address is faulty.

About the clock divider, it is true that I did not check the default value. I have measured the frequency with a logic analyzer for the 32, 16 and 8 dividers but because all were working I decided to let the default value without measuring it.

on config file uip-conf.h

I applied condition as below too (based on @romainreignier info)

  • CPU byte order.
    *
  • \hideinitializer
    */

**#if defined(ARDUINO_ARCH_STM32)

define UIP_CONF_BYTE_ORDER BIG_ENDIAN

else

define UIP_CONF_BYTE_ORDER LITTLE_ENDIAN

endif**

/**

  • Logging on or off
    *

and now UIPETHERNET work pretty well with Nucleo STM32F411RET6

and i belive is enough the patch (that i posted here) should applied too in uip-conf.h file to to as @romainreignier found it that cause problem
(BIG_ENDIAN instead LITTLE_ENDIAN should be used in case of STM32 boards) so the other files remains untouched.

so from now with your patch on Enc28J60Network.h and uip-conf.h patched too work well with STM32
i can confirm with Nucleo STM32F411RET6 also @romainreignier confirmed with his board to L476 and ping is clear and faster (but in my case i'm not changed SPI clock dividier it remais as is)

Hi @valoni
thanks for the test. Sorry, I do not have time to check in my side.
Anyway, it is strange to have to set as big endian, it should be fine to understand why.

I belive for ethernet way should be BIG_ENDIAN
not LITTLE_ENDIAN maybe this was bug in ARDUINO so original author used manually way for

..

Another problem i face but to make sure did anyone tested on Discovery STM32F407VGT6 (and can confirm work or no)-by my side seems UIPETHERNET not work on this board even with patches above (maybe is problem with clock speed)

but on the Nucleo Boards is tested and work for following boards ;

STM32F411RET6 - YES (without patched clock)
(i belive on STM32F401 will work with no problem since it close to F411 board but with less speed and ram , i will test it on GHI Brainpad board it have STM32F401 to be sure)

STM32L476 - Yes (with and without patched clock)

@valoni I think the patch I provided to you as example probably needs some review.
Maybe you could submit an issue on the UIPEthernet github librariy to have some advices (required SPI speed,...).

I mean first you need to post this patch "to make working" UIPETHERNET for now in
Nucleo 401,407,L476 ... at least " - do not forget to patch also BIG/Little ENDIANESS problem too.

and after we go in another issue - what is working and what not working parts in this way
we can optimise and find problems with STM32 CORE and going to eliminate it.

so let first make it working as it (for some of boards) and latter we fix problematic isssues.

similiar to this our ones and regards to authors

on part https://forum.pjrc.com/threads/47791-Teensy-3-2-ENC28J60-Strange-behavior?p=159635&viewfull=1#post159635 problem persist to the macros HTONS() and htons() as in this thread was from @romainreignier specified exact same problem.

Hi guys,

I've submitted the support of this core to the UIPEthernet repo with a proper fix for the endianness issue I think.
https://github.com/UIPEthernet/UIPEthernet/pull/26

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Hoel picture Hoel  路  4Comments

fpistm picture fpistm  路  7Comments

Jorgen-VikingGod picture Jorgen-VikingGod  路  8Comments

Pararera picture Pararera  路  5Comments

zhaorui4142 picture zhaorui4142  路  4Comments