PmodNIC and DNETcK with Chipkit uC32

Hi again,

I’m currently trying to program my chipkit uC32 to deal with the Microchip ENC28J60-H (Olimex version of that chip) which is an Ethernet connector managed through the SPI connector of the chipkit.

I used the PmodNIC and DNETcK libraries given here :

When I compile the following code using MPIDE I can generate a UDP server. Anyway, it compiles and it works :

// #include <NetworkShield.h>
#include <PmodNIC.h>
// #include <PmodNIC100.h>

/************************************************************************/
/*                    Required library, Do NOT comment out              */
/************************************************************************/
#include <DNETcK.h>

/************************************************************************/
/*                                                                      */
/*              SET THESE VALUES FOR YOUR NETWORK                       */
/*                                                                      */
/************************************************************************/

IPv4 ipServer = {10,104,11,100};
unsigned short portServer = 44400; 
   
//******************************************************************************************
//******************************************************************************************
//***************************** END OF CONFIGURATION ***************************************
//******************************************************************************************
//******************************************************************************************

typedef enum
{
    NONE = 0,
    LISTEN,
    ISLISTENING,
    AVAILABLECLIENT,
    ACCEPTCLIENT,
    READ,
    WRITE,
    CLOSE,
    EXIT,
    DONE
} STATE;

STATE state = LISTEN;

unsigned tStart = 0;
unsigned tWait = 5000;

// remember to give the UDP client a datagram cache
byte rgbUDPClientCache[1024];
UdpClient udpClient(rgbUDPClientCache, sizeof(rgbUDPClientCache));

// remember to give the server a datagram cache that is 
// equal or larger than the client datagram cache
const int cPending = 3; // number of clients the server will hold until accepted
byte rgbUDPServerCache[cPending * sizeof(rgbUDPClientCache)];
UdpServer udpServer(rgbUDPServerCache, sizeof(rgbUDPServerCache), cPending);

DNETcK::STATUS status;

// a read buffer
byte rgbRead[1024];
int cbRead = 0;
int count = 0;

/***    void setup()
 *
 *    Parameters:
 *          None
 *              
 *    Return Values:
 *          None
 *
 *    Description: 
 *    
 *      Arduino setup function.
 *      
 *      Initialize the Serial Monitor, and initializes the
 *      the IP stack for a static IP of ipServer
 *      No other network addresses are supplied so 
 *      DNS will fail as any name lookup and time servers
 *      will all fail. But since we are only listening, who cares.
 *      
 * ------------------------------------------------------------ */
void setup() {
  
    Serial.begin(9600);
    Serial.println("UDPEchoServer 1.0");
    Serial.println("Digilent, Copyright 2011");
    Serial.println("");

    // intialize the stack with a static IP
    DNETcK::begin(ipServer);
}

/***    void loop()
 *
 *    Parameters:
 *          None
 *              
 *    Return Values:
 *          None
 *
 *    Description: 
 *    
 *      Arduino loop function.
 *      
 *      We are using the default timeout values for the DNETck and UdpServer class
 *      which usually is enough time for the UDP functions to complete on their first call.
 *
 *      This code listens for a connection, then echos any strings that come in
 *      After about 5 seconds of inactivity, it will drop the connection.
 *
 *      This is a simple sketch to illistrate a simple UDP Server. 
 *      
 * ------------------------------------------------------------ */
void loop() {

    switch(state)
    {

    // say to listen on the port
    case LISTEN:
        if(udpServer.startListening(portServer))
        {
            Serial.println("Started Listening");
            state = ISLISTENING;
        }
        else
        {
            state = EXIT;
        }
        break;

    // not specifically needed, we could go right to AVAILABLECLIENT
    // but this is a nice way to print to the serial monitor that we are 
    // actively listening.
    // Remember, this can have non-fatal falures, so check the status
    case ISLISTENING:
        Serial.print(udpServer.isListening(&status));
        if(udpServer.isListening(&status))
        {
            Serial.print("Listening on port: ");
            Serial.print(portServer, DEC);
            Serial.println("");
            state = AVAILABLECLIENT;
        }
        else if(DNETcK::isStatusAnError(status))
        {
            state = EXIT;
        }
        break;

    // wait for a connection
    case AVAILABLECLIENT:
        if((count = udpServer.availableClients()) > 0)
        {
            Serial.print("Got ");
            Serial.print(count, DEC);
            Serial.println(" clients pending");
            state = ACCEPTCLIENT;
        }
        break;

    // accept the connection
    case ACCEPTCLIENT:
        
        // probably unneeded, but just to make sure we have
        // udpClient in the  "just constructed" state
        udpClient.close(); 

        // accept the client 
        if(udpServer.acceptClient(&udpClient))
        {
            Serial.println("Got a Connection");
            state = READ;
            tStart = (unsigned) millis();
        }

        // this probably won't happen unless the connection is dropped
        // if it is, just release our socket and go back to listening
        else
        {
            state = CLOSE;
        }
        break;

    // wait fot the read, but if too much time elapses (5 seconds)
    // we will just close the udpClient and go back to listening
    case READ:

        // see if we got anything to read
        if((cbRead = udpClient.available()) > 0)
        {
            cbRead = cbRead < sizeof(rgbRead) ? cbRead : sizeof(rgbRead);
            cbRead = udpClient.readDatagram(rgbRead, cbRead);

            Serial.print("Got ");
            Serial.print(cbRead, DEC);
            Serial.println(" bytes");
           
            state = WRITE;
        }

        // If too much time elapsed between reads, close the connection
        else if( (((unsigned) millis()) - tStart) > tWait )
        {
            state = CLOSE;
        }
        break;

    // echo back the string
    case WRITE:

        Serial.println("Writing datagram: ");  
        for(int i=0; i < cbRead; i++) 
        {
            Serial.print(rgbRead[i], BYTE);
        }
        Serial.println("");  

        udpClient.writeDatagram(rgbRead, cbRead);
        state = READ;
        tStart = (unsigned) millis();
        break;
        
    // close our udpClient and go back to listening
    case CLOSE:
        udpClient.close();
        Serial.println("Closing UdpClient");
        Serial.println("");
        state = ISLISTENING;
        break;

    // something bad happen, just exit out of the program
    case EXIT:
        udpClient.close();
        udpServer.close();
        Serial.println("Something went wrong, sketch is done.");  
        state = DONE;
        break;

    // do nothing in the loop
    case DONE:
    default:
        break;
    }

    // every pass through loop(), keep the stack alive
    DNETcK::periodicTasks(); 
}

Then I tried it with PlatformIO by including the same libraries in .platformio/lib/ and it didn’t work. I also tried to put those libraries directly in the project folder (in the lib folder) and I even sorted the libraries using the recommended method (with the scr folder into the folder of the library). It didn’t work either. I always get the same error that makes me think that the library isn’t well included :

[Tue Sep  6 15:21:53 2016] Processing chipkit_uc32 (platform: microchippic32, board: chipkit_uc32, framework: arduino)
--------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
Collected 34 compatible libraries
Looking for dependencies...
Warning! Circular dependencies detected between `/media/byran/Données/PlatformIOProjectsLinux/TestENC28J60/lib/DWIFIcK` and `/media/byran/Données/PlatformIOProjectsLinu
x/TestENC28J60/lib/DNETcK`

Warning! Circular dependencies detected between `/home/byran/.platformio/packages/framework-arduinomicrochippic32/libraries/IM8720PHY` and `/home/byran/.platformio/pack
ages/framework-arduinomicrochippic32/libraries/DEIPcK`
Warning! Circular dependencies detected between `/home/byran/.platformio/packages/framework-arduinomicrochippic32/libraries/IM8720PHY` and `/home/byran/.platformio/pack
ages/framework-arduinomicrochippic32/libraries/DEIPcK`
Library Dependency Graph
|-- <DNETcK>
|   |-- <PmodNIC>
|-- <PmodNIC>
/home/byran/.platformio/packages/tool-scons/script/../engine/SCons/Environment.py:1322: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal
val = [x for x in val if x not in dk]
Compiling .pioenvs/chipkit_uc32/src/UDPEchoServer2.o
Compiling .pioenvs/chipkit_uc32/FrameworkArduino/crtn.o
Compiling .pioenvs/chipkit_uc32/FrameworkArduino/doprnt.o
src/UDPEchoServer2.c:80:1: error: unknown type name 'IPv4'
IPv4 ipServer = {192,168,1,190};

^
src/UDPEchoServer2.c:110:1: error: unknown type name 'UdpClient'
UdpClient udpClient(rgbUDPClientCache, sizeof(rgbUDPClientCache));
^
src/UDPEchoServer2.c:110:40: error: expected ')' before 'sizeof'
UdpClient udpClient(rgbUDPClientCache, sizeof(rgbUDPClientCache));
^
src/UDPEchoServer2.c:115:6: error: variably modified 'rgbUDPServerCache' at file scope
byte rgbUDPServerCache[cPending * sizeof(rgbUDPClientCache)];
^
src/UDPEchoServer2.c:116:1: error: unknown type name 'UdpServer'
UdpServer udpServer(rgbUDPServerCache, sizeof(rgbUDPServerCache), cPending);
^
src/UDPEchoServer2.c:116:40: error: expected ')' before 'sizeof'
UdpServer udpServer(rgbUDPServerCache, sizeof(rgbUDPServerCache), cPending);
^
src/UDPEchoServer2.c:118:7: error: expected '=', ',', ';', 'asm' or '__attribute__' before ':' token
DNETcK::STATUS status;
^
src/UDPEchoServer2.c: In function 'setup':
src/UDPEchoServer2.c:146:5: error: 'Serial' undeclared (first use in this function)
Serial.begin(9600);
^
src/UDPEchoServer2.c:146:5: note: each undeclared identifier is reported only once for each function it appears in
src/UDPEchoServer2.c:152:12: error: expected expression before ':' token
DNETcK::begin(ipServer);
^
src/UDPEchoServer2.c: In function 'loop':
src/UDPEchoServer2.c:183:12: error: 'udpServer' undeclared (first use in this function)
if(udpServer.startListening(portServer))
^
src/UDPEchoServer2.c:185:13: error: 'Serial' undeclared (first use in this function)
Serial.println("Started Listening");
^
src/UDPEchoServer2.c:199:35: error: 'status' undeclared (first use in this function)
if(udpServer.isListening(&status))
^
src/UDPEchoServer2.c:202:38: error: 'DEC' undeclared (first use in this function)
Serial.print(portServer, DEC);
^
src/UDPEchoServer2.c:206:17: error: 'DNETcK' undeclared (first use in this function)
else if(DNETcK::isStatusAnError(status))
^
src/UDPEchoServer2.c:206:23: error: expected ')' before ':' token
else if(DNETcK::isStatusAnError(status))
^
src/UDPEchoServer2.c:228:9: error: 'udpClient' undeclared (first use in this function)
udpClient.close();
^
src/UDPEchoServer2.c:274:9: error: 'for' loop initial declarations are only allowed in C99 mode
for(int i=0; i < cbRead; i++)
^
src/UDPEchoServer2.c:274:9: note: use option -std=c99 or -std=gnu99 to compile your code
src/UDPEchoServer2.c:276:38: error: expected expression before 'BYTE'
Serial.print(rgbRead[i], BYTE);
^
src/UDPEchoServer2.c:308:12: error: expected expression before ':' token
DNETcK::periodicTasks();
^
*** [.pioenvs/chipkit_uc32/src/UDPEchoServer2.o] Error 255
Compiling .pioenvs/chipkit_uc32/FrameworkArduino/exceptions.o
========================== [ERROR] Took 1.97 seconds ==========================

Do I make a mistake when I copy the libraries in the folders I mentionned before ?

Can you reproduce this issue with PlatformIO 3.0?

Yes. Do you want me to repost the error messages ?

I also tried to compile the example available in .platformio/packages/framework-arduinomicrochippic32/libraries/DEIPcK/examples/UDPEchoServer/ in a proper project file and the errors seem to be quite similar.

Please report here Issues · platformio/platform-microchippic32 · GitHub

I just did it. Thanks

I’ve actually digged further and there is a

#ifdef __cplusplus
...
#endif

in the library which is not seen by the compiler since everyhing is written in C, not C++.

I’ll keep trying.

We would be thankful for any help on this issue. Thanks!

I tried to comment out the #ifdef __cplusplus in the library and it seems that PlatformIO does not deal with C++. Is this true ? Because when I go to /.platformio/packages/toolchain-microchippic32/bin/, it seems that you included pic32-c++ and g++. I probably missed something.

By the way, I also tried that code with xc32-gcc and obviously it does not work.

OK, I finally got it.

The name of my source file was UDPEchoServer.c and not UDPEchoServer.cpp, then the compiler tried to compile C code which is actually written in C++ and it doesn’t work (obviously).

Anyway, the library included in platformIO (DEIPcK) doesn’t compile for my processor (PIC32MX340F512H on uC32) but the library DNETcK (that you can have on github) compile and works after a few corrections (I had to edit the path of some includes in the headers).

Conclusion : always name your file with the extension .cpp

Yeppp! This is often mistake :frowning:
Thanks a lot that answered here!

Moreover, I achieved to compile XC32 code using platformIO (with some minor changes) by changing the extension cpp in c ! I can provide come examples if required.