Announcement

Collapse
No announcement yet.

Arduino Zero (& other SAMD21-based boards) "Teething problems."

Collapse
This topic is closed.
X
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • Arduino Zero (& other SAMD21-based boards) "Teething problems."

    G'day from New Zealand, folks.
    I'm new to the forums, but have been workin' with 4D Systems' uLCD modules on my own since 2015 (& have been workin' with the Arduino platform since 2013).

    First of all, in my arsenal of development boards, I have: 1x Arduino UNO rev3; 2x Arduino Micros; 1x Arduino Zero; 1x AdaFruit Feather M0+ BLE & (on order) 1x AdaFruit Metro M0+.
    My LCD modules are as follows: 1x uLCD220RD & 1x GEN4 uLCD50DCT-CLB.

    Before I go any further, I would like to point out that this issue has nothing to do with the LCD modules themselves & this is isolated to the host MCU (that I am using to drive one of my LCD modules with). So far I have had no issues with any of my hardware (including the LCD modules) up until about the previous two updates to the 4DGL & Workshop 4 IDE.

    Here's the problem: When I flash any of my SAMD21-based boards with any code that uses the 4D Diablo Serial Library for Arduino, it crashes the chipset (in which the code's been uploaded to). By "crash", I mean the program that I upload to (say, for example,) my Arduino Zero, the program simply will not initialize, period. At first, I thought it was my Zero that was at fault (& I falsely concluded this, when I flashed all of my AVR-based boards with the attached "Hello World" sketch). After that, I flashed my Feather M0 with the same "Hello World" sketch to verify my initial conclusion... only to find out that I was wrong & in fact, this has turned out to be an issue with the Diablo Serial 4D Library itself, as my Feather M0 crashed in the same way as my Arduino Zero did.

    About three updates ago, I have had no issues, period. The Diablo Serial Library for Arduino has worked flawlessly on all of my SAMD21-based boards in the past & I can not (for the life of me) put my finger on why I am getting system crashes now, apart from a couple of recent updates to the Diablo Serial 4D Library.

    Here is the "Hello World" test sketch I have created to test my 4D LCD modules.
    What this sketch does is, it lights up the built-in LED, runs the LCD module's startup sequence & once the LCD module has been initialized, it prints the phrase "Hello World" to a connected LCD module & then turns the built-in LED off. Whenever the sketch encounters an issue with the screen, it'll stop the program & blink the built-in LED at a rate of about 5 Hz.
    This sketch runs flawlessly on all of my AVR-based boards (my UNO & my two Micros), but my SAMD21-based boards (my Zero & my Feather M0)? That's where the 'system crash' problem lies.

    Code:
    //////////////////////////////////////////////////////////////////// Libraries:
    #include <Diablo_Const4D.h>                                       // 
    #include <Diablo_Serial_4DLib.h>                                  // 
    
    //////////////////////////////////////////////////////////////////// Global Constants:
    #define printMessages false                                       // 
    #define screenOrientation LANDSCAPE                               // 
    #define LCD_BAUD 115200                                           // 
    #define LCD_SerialTimeout 5000                                    // 
    #define LCD_Serial Serial1                                        // 
    const uint8_t LCD_ResetLine=4;                                    // 
    
    //////////////////////////////////////////////////////////////////// Global Variables:
    bool LED_State;                                                   // 
    
    //////////////////////////////////////////////////////////////////// Objects:
    Diablo_Serial_4DLib Display(&LCD_Serial);                         // 
    
    //////////////////////////////////////////////////////////////////// Program Startup:
    void setup() {                                                    // 
      #if printMessages                                               // 
      Serial.begin(115200);                                           // 
      Serial.println("Starting LCD test...");                         // 
      #endif                                                          // 
      pinMode(LED_BUILTIN,OUTPUT);                                    // 
      if(!LED_State){                                                 // 
        LED_State=!LED_State;                                         // 
        digitalWrite(LED_BUILTIN,LED_State);                          // 
      }
      pinMode(LCD_ResetLine,OUTPUT);                                  // 
      digitalWrite(LCD_ResetLine,HIGH);                               // 
      delay(100);                                                     // 
      digitalWrite(LCD_ResetLine,LOW);                                // 
      delay(3000);                                                    // 
      LCD_Serial.begin(115200);                                       // 
      Display.TimeLimit4D=LCD_SerialTimeout;                          // 
      Display.Callback4D=LCD_ErrCallback;                             // 
      Display.gfx_ScreenMode(screenOrientation);                      // 
      Display.gfx_MoveTo(0,0);                                        // 
      Display.putstr("Hello World.\r\n");                             // 
      if(LED_State){                                                  // 
        LED_State=!LED_State;                                         // 
        digitalWrite(LED_BUILTIN,LED_State);                          // 
      }
    }
    
    //////////////////////////////////////////////////////////////////// Main Program:
    void loop() {}                                                    // Nothing to do here.
    
    //////////////////////////////////////////////////////////////////// ISRs & Subroutines:
    void LCD_ErrCallback(int ErrCode,unsigned char ErrByte){          // 
      #if printMessages                                               // 
      const char *LCD_ErrStr[] = {"OK\t","Timeout\t","NAK\t","Length\t","Invalid\t"}; // 
      Serial.print(F("LCD Error: "));                                 // 
      Serial.print(LCD_ErrStr[ErrCode]);                              // 
      if(ErrCode==Err4D_NAK){                                         // 
        Serial.print(F("Returned data: "));                           // 
        Serial.print(ErrByte);                                        // 
        Serial.println();                                             // 
      }else{                                                          // 
        Serial.println();                                             // 
        return;                                                       // 
      }
      #else                                                           // 
      while(true)blinkErrLED();                                       // 
      #endif                                                          // 
    }
    
    void blinkLED(uint32_t mark,uint32_t space){                      // 
      static uint64_t msCount0,msCount1;                              // 
      if(mark==space){                                                // 
        if(msCount0>millis())msCount0=millis();                       // 
        if(millis()-msCount0>=mark){                                  // 
          msCount0=millis();                                          // 
          LED_State=!LED_State;                                       // 
          digitalWrite(LED_BUILTIN,LED_State);                        // 
        }
      }else{                                                          // 
        if(msCount0>millis())msCount0=millis();                       // 
        if(msCount1>millis())msCount1=millis();                       // 
        if(millis()-msCount0>=mark){                                  // 
          msCount0=millis();                                          // 
          if(LED_State){                                              // 
            LED_State=!LED_State;                                     // 
            digitalWrite(LED_BUILTIN,LED_State);                      // 
          }
        }
        if(millis()-msCount1>=space){                                 // 
          msCount1=millis();                                          // 
          if(!LED_State){                                             // 
            LED_State=!LED_State;                                     // 
            digitalWrite(LED_BUILTIN,LED_State);                      // 
          }
        }
      }
    }
    
    void blinkErrLED(void){                                           // 
      blinkLED(200,200);                                              // 
    }
    To reiterate, I have tested this sketch with all of my AVR-based boards (that is, my Arduino UNO r3 & both of my Arduino Micro boards) & this sketch runs flawlessly as it should.
    However, uploading any sketch that uses the 4D Diablo Serial Library for Arduino on any of my SAMD21-based boards (Either my Arduino Zero or my AdaFruit Feather M0) causes the boards to crash & the code will not run, period.

    Any help with this would be greatly appreciated.
    The only limitation you have in life is yourself.

  • #2
    Hello

    Welcome to the forum,

    The only thing I can see in the code which won't cause a crash, but would keep the display in reset is the reset code. Are you using 4D adapter shields on the Arduino's that work. The reset code is correct for an adapter shield but isn't right if the reset line is coming directly from D4.

    This is the reset code without an adapter shield.

    Code:
      pinMode(LCD_ResetLine,OUTPUT);                              
      digitalWrite(LCD_ResetLine,LOW);                              
      delay(100);                                                    
      digitalWrite(LCD_ResetLine,HIGH);
      delay(3000);
    Does the LED blink as expected?

    Best regards

    Paul

    Comment


    • #3
      I've used the 4D adapter shield on everything but my Feather M0 (for obvious reasons & I'd simply reverse the states of the 'LCD_ResetLine'), along with the hardware Serial1 ("Serial" for my UNO) port (pins' D0 & D1).
      Generally, what I'll do with the built-in LED is switch it on during the 'setup()' routine (to tell me that the program is actually running) & if anything goes awry (EG if I'm trying to mount a uSD Card & it failed to mount), the 'setup()' routine would stop & blink the built-in LED ad-infinitum - telling me that something went wrong. However, in this case, the built-in LED won't light up, period.

      Another thing I'd like to point out is, once I've uploaded this code to any of my SAMD21-based boards (my Zero or my Feather M0) via the native USB port, the USB port won't reconnect after the program has been uploaded either (This is the same reason as to why the built-in LED won't light up). I'm glad that the bootloader can be accessed by double-tapping the reset button, to upload other code (that actually works, such as the default "blink" example) to them.
      The only limitation you have in life is yourself.

      Comment


      • #4
        I had another read through the application note: "Serial Connection to an Arduino Host" & I saw the section "Modify the Library for the Arduino Due" & thought "Hmmm. The Arduino Due & the Arduino Zero share a similar architecture, I wonder what would happen if I did this...?"

        So, what I did was, rather than commenting out the line in "Diablo_Serial_4DLib.cpp" that reads "_virtualPort->flush();"
        I've wrapped it with an "#ifdef(ARDUINO_ARCH_AVR)" macro. So, it looks like this:
        Code:
        Diablo_Serial_4DLib::Diablo_Serial_4DLib(Stream * virtualPort) {
          _virtualPort = virtualPort;
          #if defined(ARDUINO_ARCH_AVR)
          _virtualPort->flush();
          #endif
        }
        The library now works like a charm for all of my Arduino boards now (for all of my SAMD21-based & AVR-based boards). I've used an "#ifdef" macro to preserve a little backward-compatibility with the AVR platform (EG Arduino UNO, Leonardo, Mega2560 etc), whilst maintaining compatibility for next-gen Arduino boards (EG the Arduino Due & Arduino Zero).
        I have also taken the liberty & done the same thing to the Goldelox & Picaso versions of the Diablo Serial library for Arduino & I have linked all three '.cpp' files here.

        Would it be possible for you guys, on the 4D team to include my little modification to the library files in your next software updates?
        Attached Files
        The only limitation you have in life is yourself.

        Comment


        • #5
          thats weird, flush() is core defined and part of the stream class, this shouldnt be a library problem, more of a core issue with the SAM controller, flush() is not a function of the library, its only action is “nothing” as programmed on some controllers, or a wait state to finish off all transfers in the transmit buffer before continuing the sketch. Your essentially letting the SAM (with that define) send the data out as it wants without letting it complete, which is fine. I’d also like to mention, even for AVR’s, flush() shouldnt be needed anyways. But, like i said, this is a SAM core issue, and not this library, removing the flush() entirely is an acceptable choice, for any microcontroller, as it costs a few microseconds of wait time to empty the transmit buffer

          Comment


          • #6
            So, theoretically, 'flush()' should only take a few microseconds to empty the transmit buffer before it can allow the user's sketch to continue, right?

            'Cause in my case, it appears to indefinitely halt my sketches when they're loaded onto any one of my SAMD21 chips - to the point where the native USB port won't even reconnect after the sketch has been uploaded (& by "reconnect", I mean the COM port won't even show up under the 'Tools -> Port' menu in the Arduino IDE).

            I'm also wonderin' if I should take this issue up with Arduino themselves? Especially given that 'flush()' is a part of the Stream class (as Tonton81 pointed out).

            Also, is 'flush()' absolutely necessary on the SAMD21 chips? 'Cause it seems to me that all of my sketches run perfectly good & fine without it (granted all I'm doin' with the LCD modules is displaying custom gauges/indicators & the occasional touch-screen button here & there).
            The only limitation you have in life is yourself.

            Comment


            • #7
              flush() is not needed at all, the blocking it does can make you “miss” uart data if the receiving overflows or your interrupt doesnt capture the received byte to the uart queue

              you can safely remove it (not just for 4D screens, but any other devices as well)

              Comment


              • #8
                Ah, good. Thank you very much. That's what I wanted to know. Thanks for all your help, guys.

                Admins can feel free to close this topic if they so wish. No further correspondence is necessary in this thread & if need be, admins have my permission to 'sticky' this thread for future reference (IE other people run into the same problem, later down the track etc).
                The only limitation you have in life is yourself.

                Comment


                • #9
                  ZZ Cat,

                  Glad to know that your problem has been solved.
                  Closing this topic means that the topic “Teething problems” has been officially answered.

                  Topic will be closed with the permission of the topic starter.

                  Thank you and best regards,
                  Eran
                  Eran

                  Comment

                  Working...
                  X