Modulino Light - Arduino App Lab - Arduino UNO Q STM32U585 is crashing

I am using 7 Modulino modules on the Arduino UNO Q STM32 I2C bus.
Six modules are working without any problem.

If I add the Light module in my application the system is crashing. Compiling and linking of the Light module - not calling begin() or using it - is enough.

Inside of the Modulino library a static instance is getting used:

File: LTR381RGB.h

Line 108: extern LTR381RGBClass RGB;

The Modulino library has the following version and refers to Arduino_LTR381RGB:

  • dependency: Arduino_LTR381RGB (1.0.1)
  • Arduino_Modulino (0.8.0)

Maybe this "singleton" is the root cause that the STM32 images is crashing?

Sorry, I don't have your hardware, nor your program to look at, but
creating a new App in App lab, with just:

#include <Arduino_Modulino.h>
#include <Arduino_LTR381RGB.h>

void setup() {
  Serial.begin(115200)
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  delay(500);
}

Does not crash as far as I can tell. Nothing in monitor and the LED is blinking like once per second.

Now if I add in the begin like some of their examples:

#include <Arduino_Modulino.h>
#include <Arduino_LTR381RGB.h>

void setup() {
  Serial.begin(115200);
  // put your setup code here, to run once:
  pinMode(LED_BUILTIN, OUTPUT);
  if (!RGB.begin()) {
    Serial.println("Failed to initialize rgb sensor!");
    while (1);
  }

}

void loop() {
  // put your main code here, to run repeatedly:
  digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
  delay(500);
}

It fails in the RGB.begin() as I don't have one and then prints out
error message and loops for ever, looking like it is hung.

Now on UNO Q Serial goes currently out to the Hardware Serial object that uses pins 0, 1.
I have a USB to Serial Adapter hooked up to it with a Terminal window connected and
sure enough I see:

*** Booting Zephyr OS build v4.2.0-44-g7cfc53a6f3fc ***
Invalid sketch header
Failed to initialize rgb sensor!

Which is as the program specified and Now I don't have blinking LED

Hi @qudorino. Please provide the contents of the App's sketch/sketch.ino file. I'll provide instructions you can follow to do that:

  1. Open the App in Arduino App Lab.
  2. Click the β–Έ icon next to the "sketch" folder item under the "Files" section of the left hand panel in the Arduino App Lab window.
    The item will expand to show the contents of the sketch folder.
  3. Select "sketch.ino" from the list of contents of the folder.
    sketch.yaml will open in the editor panel of the Arduino App Lab window.
  4. Click on the editor panel.
  5. Press the Ctrl+A keyboard shortcut (Command+A for macOS users).
    The contents of the editor panel will be selected.
  6. Press the Ctrl+C keyboard shortcut (Command+C for macOS users).
    This will copy the selected text to the clipboard.
  7. Open a reply here on this forum topic by clicking the "Reply" button.
  8. Click the <CODE/> icon on the post composer toolbar.
    This will add the forum's code block markup (```) to your reply to make sure the content is correctly formatted.
  9. Press the Ctrl+V keyboard shortcut (Command+V for macOS users).
    This will paste the copied sketch.yaml file content into the code block.
  10. Move the cursor outside of the code block markup before you add any additional text to your reply.
  11. Click the "Reply" button to publish the post.

@qudorino

To run the above program @KurtE, the OP needs to follow these steps:
1. Make the following setup of Fig-1:


Figure-1:

2. Open IDE 2.3.X or App Lab
3. Upload the above sketch @KurtE .
4. Open (another) IDE from Start icon.
5. Detect the Serial port (0, 1) at the correct COM Port.
6. Open Serial Monior at Bd = 115200.
7. Read the message that has appeared on the Outputox of Serial Monitor.

profiles:
  default:
    fqbn: 
    platforms:
      - platform: arduino:zephyr
    libraries:
      - Arduino_RouterBridge (0.4.1)
      - Arduino_RPClite (0.2.1)
      - ArxContainer (0.7.0)
      - ArxTypeTraits (0.3.2)
      - DebugLog (0.8.4)
      - MsgPack (0.4.2)
      - Button2 (2.5.0)
      - dependency: ArduinoGraphics (1.1.5)
      - dependency: Arduino_HS300x (1.0.0)
      - dependency: Arduino_LPS22HB (1.0.2)
      - dependency: Arduino_LSM6DSOX (1.1.2)
      - dependency: Arduino_LTR381RGB (1.0.1)
      - Arduino_Modulino (0.8.0)
      - dependency: STM32duino VL53L4CD (1.0.5)
      - dependency: STM32duino VL53L4ED (1.0.1)

default_profile: default

On the terminal the following output is common for any started program:

*** Booting Zephyr OS build v4.2.0-44-g7cfc53a6f3fc ***
Invalid sketch header

bool FactoryC::Begin(void)
{
   printLn("\n\nFactory Begin \n\n");
   bool ok{true};

   mButtonsDrv.Begin();
   mBuzzerDrv.Begin();
   mDistanceDrv.Begin();
   mKnobDrv.Begin();
   //mLightDrv.Begin();  --> no crash
   mPixelsDrv.Begin();
   mThermoDrv.Begin();

   return(ok);  
}

bool FactoryC::Begin(void)
{
   printLn("\n\nFactory Begin \n\n");
   bool ok{true};

   mButtonsDrv.Begin();
   mBuzzerDrv.Begin();
   mDistanceDrv.Begin();
   mKnobDrv.Begin();
   mLightDrv.Begin();  --> now crashing
   mPixelsDrv.Begin();
   mThermoDrv.Begin();

   return(ok);  
}
#include "LightDrv.h"
#include <Modulino.h>

LightDrvC::LightDrvC()
  : mLight{}
{
  
}
// I use a tiny wrapper to be later extended (LightDrvC is nothing doing for now):

// The bass class is responsible to initialize the "modulino lib" once, 
// independent how the Begin() call order of the other six drivers are: 
#include "ModulinoBase.h"
#include <Modulino.h>
#include "../Trace/Log.h"

bool ModulinoBaseC::mInitDone{false};

void ModulinoBaseC::ModulinoBegin(void)
{
   printLn("\n\nModulino Base Begin \n\n");
   if(not mInitDone)
   {
      printLn("\n\nModulino Begin \n\n");
      mInitDone = true;
      Modulino.begin();
   }
}



void LightDrvC::Begin(void)
{
   ModulinoBegin();
   mLight.begin();
}

I do not allocate any dynamic memory in my application code.
The memory footprint of my application class are ~1.500 bytes.

With the terminal the following happen if I enable one line code:

*** Booting Zephyr OS build v4.2.0-44-g7cfc53a6f3fc ***
Invalid sketch header
[00:00:00.234,000] <err> os: ***** BUS FAULT *****
[00:00:00.240,000] <err> os:   Precise data bus error
[00:00:00.245,000] <err> os:   BFAR Address: 0x203721ac
[00:00:00.251,000] <err> os: r0/a1:  0x00011acd  r1/a2:  0x203721a0  r2/a3:  0x00000003
[00:00:00.260,000] <err> os: r3/a4:  0x000070c4 r12/ip:  0x000003ff r14/lr:  0x08013ea1
[00:00:00.269,000] <err> os:  xpsr:  0x29002c00
[00:00:00.274,000] <err> os: s[ 0]:  0x0000400c  s[ 1]:  0x20032990  s[ 2]:  0x00000001  s[ 3]:  0x200296a8
[00:00:00.284,000] <err> os: s[ 4]:  0x00000002  s[ 5]:  0x08013f19  s[ 6]:  0x00000002  s[ 7]:  0x20032990
[00:00:00.295,000] <err> os: s[ 8]:  0x200334c2  s[ 9]:  0x200296a8  s[10]:  0x00000001  s[11]:  0x20029640
[00:00:00.305,000] <err> os: s[12]:  0xffffffff  s[13]:  0x0801423b  s[14]:  0x00000000  s[15]:  0x00000001
[00:00:00.315,000] <err> os: fpscr:  0x200334c2
[00:00:00.321,000] <err> os: Faulting instruction address (r15/pc): 0x08013dd6
[00:00:00.329,000] <err> os: >>> ZEPHYR FATAL ERROR 25: Unknown error on CPU 0
[00:00:00.336,000] <err> os: Current thread: 0x20000590 (main)
[00:00:00.343,000] <err> os: Halting system

The trace output is telling me, that the root cause could not easy be found. I think it
is not the first time I am running into this problem. I have rearranged my code many times again and again. If I rearrange my code it is running for a longer time stable till adding something simple the next crash is there.

That is useful information, but it is the contents of the sketch/sketch.yaml file. I asked you to provide the contents of the sketch/sketch.ino file (note the .ino file extension).

Please provide that information and I'll investigate.

The "beginning" of many test code in the .ino file:

#include "Arduino_RouterBridge.h"

// MPU <-> MCU communication:
#include "src/BridgeMsg/BaseProxy.h"
#include "src/BridgeMsg/Messages.h"

// Moves later into MainC
#include "src/Hardware/MatrixLedDrv.h"
#include "src/Hardware/ButtonsDrv.h"
#include "src/Hardware/KnobDrv.h"
#include "src/Hardware/PixelsDrv.h"

// Application:
#include "src/Main/Main.h"

#include <cstdint>
#include <cstdio>
#include <cstring>
#include <ctime>



/*
 *   STM32U585AII6TR BGA169P
 *   ----------------------------------------------------------------
 *     Ultra-low-power with FPU Arm Cortex-M33 MCU with TrustZone,
 *     160 MHz with 
 *       2 MB FLASH (2 banks)
 *     786 KB SRAM
 **********************************************************************/

MatrixLedDrvC       mMatrixLedDrv;

// Till having a new interface for proxy usage:
#include "src/BridgeMsg/TimeSyncProxy.h"
extern TimeSyncProxyC mTimeSyncProxy;

// Inbound messages:
MessageU  messages;

constexpr size_t MSG_SIZE = 128;
using FrameBuffer = std::array<uint8_t, MSG_SIZE>;
static_assert(sizeof(messages) == MSG_SIZE, "size mismatch!");

//Bridge callback with messages from MPU to MCU:
std::int32_t transport(FrameBuffer iFrame)
{
   //printLn("Frame size: %d", iFrame.size());
   std::memcpy(messages.Buffer, iFrame.data(), iFrame.size());

   std::int32_t instance = messages.Msg.header.instance;
   std::int32_t method   = messages.Msg.header.method;

   switch(instance)
   {
      case INST_LED_RED:
      {
         //Monitor.println("INST_LED_RED called");
         digitalWrite(LED3_R, method ? LOW : HIGH);
         break;
      }
    
      case INST_LED_GREEN:
      {
         //Monitor.println("INST_LED_GREEN called");
         digitalWrite(LED3_G, method ? LOW : HIGH);
         break;
      }
    
      case INST_LED_BLUE:
      {
         //Monitor.println("INST_LED_BLUE called");
         digitalWrite(LED3_B, method ? LOW : HIGH);
         break;
      }

      case INST_M_LED:
      {
         if(method == M_DRAW_PIXEL)
         {
            MatrixLedDrvC::PixelS pixel;
           
            pixel.x = messages.Msg.pixel.x;
            pixel.y = messages.Msg.pixel.y;
            pixel.b = messages.Msg.pixel.b;
          
            mMatrixLedDrv.DrawPixel(pixel);
         }
         
         else if(method == M_DRAW_FRAME)
         {
            MatrixLedDrvC::FrameS frame;
          
            std::memcpy(frame.data,
                        messages.Msg.matrix.FrameBuffer,
                        MatrixLedDrvC::FRAME_SIZE);

            mMatrixLedDrv.LoadFrame(frame);
         }
      
         break;
      }

      case INST_M_ANIMATION:
      {
         Monitor.println("INST_M_ANIMATION");
         if(method == M_LOAD_FRAME)
         {
            Monitor.println("M_LOAD_FRAME");
         }
         else if(method == M_START)
         {
            Monitor.println("M_START");
         }
         else if(method == M_STOP)
         {
            Monitor.println("M_STOP");
         }
        
         break;
      }
     
      case INST_MPU_TIME_SYNC_SERVICE:
      {
         Monitor.println("INST_MPU_TIME_SYNC_SERVICE");

         if(method == M_UTC_TIME_CONF)
         {
            std::uint64_t utcTime = messages.Msg.time.Utc;

            DateTime dt = utc_from_epoch(utcTime);
            printLn("------->  %04d-%02d-%02d %02d:%02d:%02d UTC\n",
            dt.year, dt.month,  dt.day,
            dt.hour, dt.minute, dt.second);

            mTimeSyncProxy.SetUtcTime(utcTime);
         }
        
         break;
      }
         
      default:
      {
         Monitor.println("Bad instance");
         break;
      }
   }
  
   return(1);
}


// Proxy for outgoing messages (string message for Python instances)
// -----------------------------------------------------------------
//                   reveiver instance
//                   | method number 0..n
//                   | | +-+-+--- optional 3 parameter
//                   V V V V V
// Message to MPU: [12:0:0:0:0]  e.g., time sync reveived response
BaseProxyC   mpuProxy;

/*
 * Whatever the reason is;
 * - This method needs to be static!
 * - The Bridge.call(...) implementation needs to be in the *.ino file
 *   where "Arduino_RouterBridge.h" is getting included only once.
 ***************************************************************************/
bool BaseProxyC::SendFunction(const char* text)
{
   bool status;
   Bridge.call("MPU", text).result(status);
   printLn("Message to MPU: [%s]", text);
   return(status);  
}

// ---------------------------------------------------------------------
extern ButtonsDrvC  mButtonsDrv;
extern BuzzerDrvC   mBuzzerDrv;
extern KnobDrvC     mKnobDrv;
extern PixelsDrvC   mPixelsDrv;

// ---------------------------------------------------------------------
void test_malloc(const char* where)
{
    printLn("Testing malloc in ");
    printLn(where);

    void* p = malloc(256);

    if (p == nullptr)
    {
        printLn("malloc FAILED");
    }
    else
    {
        printLn("malloc OK");

        // touch memory to ensure it is valid
        memset(p, 0xAA, 256);

        free(p);
        printLn("free OK");
    }
}


// Application instance, ~1.500 Byte
static APP::MainC mMain;


void setup()
{
    Bridge.begin();
    delay(10);
  
    Monitor.begin();
    delay(10);

    // Contains HW and Ardino platform basics:
    mMain.LowLevelBegin();

    // Communication MPU --> MCU open:
    Bridge.provide("MCU", transport);
    delay(10);
  
    mMatrixLedDrv.Begin();
    delay(10);
  
    // --- Wait until Linux host signals ready ---
    bool mpu_started{false};
    while(not mpu_started) 
    {
        Bridge.call("mpu_check").result(mpu_started);
        delay(10);
    }

    // Test message to MPU:
    if(mpuProxy.Send(1, 2, 555, 49, 59))
    {
        Monitor.println("\n\nMPU call succeeded\n\n");
    }
  
    Bridge.call("mcu_note", "Hello world, STM32U585AI has started!");
    Monitor.println("STM32U585 - Online");

    printLn("\n\nMain size: %d Bytes\n\n", sizeof(mMain));

    // Application init:
    bool ok = mMain.Begin();

    if(ok)
    {
       printLn("\n\nMain: init ok! \n\n");
    }

    else
    {
       printLn("\n\nMain: init failed! \n\n");  
    }
  
    printLn("\n\nC++ Standard: %ld\n\n", __cplusplus);
    //test_malloc("setup()");
}

// For test purpose (later moving into MainC):
std::int32_t  position{0};
std::uint32_t pixelNumber{0};
std::uint32_t pixelColor{0};

bool once{true};
bool changeColor{false};

/*
 * The loop is running independent of th Bride callback(s).
 * The main loop is not getting interrupted for a long time.
 */
void loop()
{ 
   if(once)
   {      
      once = false;
      bool mpu_ready = false;

      // --- Timestamp before sending the request ---
      unsigned long t_start = micros();

      // --- Single Bridge call to check MPU readiness ---
      Bridge.call("mpu_check").result(mpu_ready);

      // --- Timestamp after the response is received ---
      unsigned long t_end = micros();

      // --- Print the round-trip time ---
      printLn("Single Bridge round-trip: %lu us, mpu_ready=%d\n", t_end - t_start, mpu_ready);
     
      //test_malloc("loop()");

      // Test message 2 of 2 to MPU:
      if(mpuProxy.Send(1, 2, 500, 49, 59)) 
      {
         Monitor.println("\n\nMPU call succeeded\n\n");
      }
     
      mBuzzerDrv.Beep();     
      delay(500);
      mBuzzerDrv.Off();

      mPixelsDrv.Clear();
      delay(3000);

      mPixelsDrv.SetPixel( 0, RED,    5);
      mPixelsDrv.SetPixel( 1, BLUE,   5);
      mPixelsDrv.SetPixel( 2, GREEN,  5);
      mPixelsDrv.SetPixel( 3, YELLOW, 5);
      mPixelsDrv.SetPixel( 4, VIOLET, 5);
      mPixelsDrv.SetPixel( 5, CYAN,   5);
      mPixelsDrv.SetPixel( 6, WHITE,  5);
      mPixelsDrv.SetPixel( 7, WHITE,  5);
      mPixelsDrv.Show();
#if 1
      delay(3000);
     
      bool a{true};
      bool b{true};
      bool c{true};
      bool k{true};

      position = mKnobDrv.Position();
      mButtonsDrv.SetLeds(a,b,c);   
      delay(500);
     
      while(a or b or c or k)
      {
         while(     (not mButtonsDrv.IsPressed())
                and (not mKnobDrv.IsPressed())
              )
         {
            // wait until button pressed
         }

         if(mButtonsDrv.IsAButtonPressed())
         {
            printLn("\n\nButton [a] pressed!\n\n");
            a = false;
         }
         
         if(mButtonsDrv.IsBButtonPressed())
         {
            printLn("\n\nButton [b] pressed!\n\n");
            b = false;
         }

         if(mButtonsDrv.IsCButtonPressed())
         {
            printLn("\n\nButton [c] pressed!\n\n");
            c = false;
         }

         if(mKnobDrv.IsPressed())
         {
            printLn("\n\nButton [k] pressed!\n\n");
            k = false;
            mPixelsDrv.Clear();
            mPixelsDrv.Show();
         }

         mButtonsDrv.SetLeds(a,b,c);

         delay(200);
      }

      delay(1000);
   } // once
 
   if(mKnobDrv.IsPressed())
   {
      changeColor = true;
      Monitor.println("\n\nColor changed!  \n\n");
      pixelColor++;
      pixelColor &= 0b11;
      Monitor.println(pixelColor);
      delay(1000);
   }

   if( (position != mKnobDrv.Position()) or changeColor)
   {
      changeColor = false;
      position    = mKnobDrv.Position();  
      std::int8_t direction = mKnobDrv.Direction();

      printLn("\n\nRotary values: %d %d \n\n", position, direction);

      pixelNumber += direction;

      mPixelsDrv.Clear();
     
      if(pixelNumber >= 8 and pixelNumber < 200)
      {
         pixelNumber = 0;
      }

      else if(pixelNumber > 10000)
      {
         pixelNumber = 7;
      }

      if(pixelColor == 0)
      {
         mPixelsDrv.SetPixel( pixelNumber, RED, 10);
      } 
      
      else if(pixelColor == 1)
      {
         mPixelsDrv.SetPixel( pixelNumber, GREEN, 10);
      }
        
      else if(pixelColor == 2)
      {
         mPixelsDrv.SetPixel( pixelNumber, BLUE, 10);
      }
        
      else
      {
         mPixelsDrv.SetPixel( pixelNumber, WHITE, 10);
      } 
     
      mPixelsDrv.Show();
#endif
   }

   // Protothread scheduling
   bool ok = mMain.Run();
}

sketch/
β”œβ”€β”€ prj.conf
β”œβ”€β”€ sketch.ino
β”œβ”€β”€ sketch.yaml
└── src
    β”œβ”€β”€ Application
    β”‚   β”œβ”€β”€ DistanceService.cpp
    β”‚   β”œβ”€β”€ DistanceService.h
    β”‚   β”œβ”€β”€ LedBlinking.cpp
    β”‚   β”œβ”€β”€ LedBlinking.h
    β”‚   β”œβ”€β”€ MatrixLedService.cpp
    β”‚   β”œβ”€β”€ MatrixLedService.h
    β”‚   β”œβ”€β”€ MelodyService.cpp
    β”‚   β”œβ”€β”€ MelodyService.h
    β”‚   β”œβ”€β”€ PixelsDemo.cpp
    β”‚   β”œβ”€β”€ PixelsDemo.h
    β”‚   β”œβ”€β”€ SensorService.cpp
    β”‚   β”œβ”€β”€ SensorService.h
    β”‚   β”œβ”€β”€ Services.cpp
    β”‚   β”œβ”€β”€ Services.h
    β”‚   β”œβ”€β”€ TimeSyncService.cpp
    β”‚   β”œβ”€β”€ TimeSyncService.h
    β”‚   β”œβ”€β”€ ZephyrTestService.cpp
    β”‚   └── ZephyrTestService.h
    β”œβ”€β”€ BridgeMsg
    β”‚   β”œβ”€β”€ BaseProxy.cpp
    β”‚   β”œβ”€β”€ BaseProxy.h
    β”‚   β”œβ”€β”€ Messages.h
    β”‚   β”œβ”€β”€ TimeSyncProxy.cpp
    β”‚   └── TimeSyncProxy.h
    β”œβ”€β”€ Hardware
    β”‚   β”œβ”€β”€ ButtonsDrv.cpp
    β”‚   β”œβ”€β”€ ButtonsDrv.h
    β”‚   β”œβ”€β”€ BuzzerDrv.cpp
    β”‚   β”œβ”€β”€ BuzzerDrv.h
    β”‚   β”œβ”€β”€ DistanceDrv.cpp
    β”‚   β”œβ”€β”€ DistanceDrv.h
    β”‚   β”œβ”€β”€ Factory.cpp
    β”‚   β”œβ”€β”€ Factory.h
    β”‚   β”œβ”€β”€ IFactory.h
    β”‚   β”œβ”€β”€ KnobDrv.cpp
    β”‚   β”œβ”€β”€ KnobDrv.h
    β”‚   β”œβ”€β”€ LightDrv.cpp
    β”‚   β”œβ”€β”€ LightDrv.h
    β”‚   β”œβ”€β”€ MatrixLedDrv.cpp
    β”‚   β”œβ”€β”€ MatrixLedDrv.h
    β”‚   β”œβ”€β”€ ModulinoBase.cpp
    β”‚   β”œβ”€β”€ ModulinoBase.h
    β”‚   β”œβ”€β”€ PixelsDrv.cpp
    β”‚   β”œβ”€β”€ PixelsDrv.h
    β”‚   β”œβ”€β”€ RfidDrv.h
    β”‚   β”œβ”€β”€ ThermoDrv.cpp
    β”‚   └── ThermoDrv.h
    β”œβ”€β”€ Main
    β”‚   β”œβ”€β”€ Main.cpp
    β”‚   β”œβ”€β”€ Main.h
    β”‚   β”œβ”€β”€ QuinoBoard.cpp
    β”‚   └── QuinoBoard.h
    β”œβ”€β”€ OS
    β”‚   β”œβ”€β”€ ZephyrUnoQ.cpp
    β”‚   └── ZephyrUnoQ.h
    β”œβ”€β”€ ProtoThread
    β”‚   β”œβ”€β”€ ProtoThread.h
    β”‚   └── pt
    β”‚       β”œβ”€β”€ lc-addrlabels.h
    β”‚       β”œβ”€β”€ lc.h
    β”‚       β”œβ”€β”€ lc-switch.h
    β”‚       β”œβ”€β”€ pt.h
    β”‚       └── pt-sem.h
    β”œβ”€β”€ Retarget
    β”‚   └── exception_dummies.cpp
    β”œβ”€β”€ Timer
    β”‚   β”œβ”€β”€ Timer.cpp
    β”‚   └── Timer.h
    β”œβ”€β”€ Trace
    β”‚   β”œβ”€β”€ Log.h
    β”‚   └── MonitorTrace.cpp
    └── ZephyrThread
        └── ZephyrThread.h

I see. I recommend you create a sketch that contains only the absolute minimum amount of code required to produce the crash.

I find that often by the time I have completed this work the cause of the fault has become clear to me. Even if it doesn't, you can then share that "MCVE" here on the forum. It is likely that information will enable us to more effectively investigate and assist.

This often implies to me, there is an underlying problem with the code, either in system, or libraries, or your code. Some of the common ones I have run into include:
a) you write outside the bounds of an array: for example like:

uint8_t my_array[3];
...
my_array[3] = 0;

Or potentially worse, negative index.

b) using an uninitialized variable.

c) running out of memory, like stack space, which could be by recursion or having large arrays on the stack... Sometimes it causes the stack to run into the global variables, which get clobbered.

...

But your crash report may give you some insights on where it crashed!

You might be able to gain some information, from looking at the output
from the build.

For example if run an app on my Q4, lets say my weather2
If you open up a command prompt to your Q. Not sure how you are running it, but if connected to pc, could use the >_ icon bottom leftish of screen.

And look in the apps .cache directory like at:
~/ArduinoApps/weather2/.cache/sketch
Obviously change weather2 to your app name.

And look at the stuff there:

arduino@Uno-Q4:~/ArduinoApps/weather2/.cache/sketch$ ls
build.options.json     includes.cache   rodata_split.ld  sketch.ino.bin-zsk.bin  sketch.ino.elf          sketch.ino.map
compile_commands.json  libraries        sketch           sketch.ino_check.tmp    sketch.ino.elf-zsk.bin  sketch.ino_temp.elf
core                   libraries.cache  sketch.ino.bin   sketch.ino_debug.elf    sketch.ino.hex          sketch.ino_temp.map
arduino@Uno-Q4:~/ArduinoApps/weather2/.cache/sketch$

I don't remember if addr2line command is installed automatically or not, but
if it works, it might give hint, if not maybe the map files.
However with applab builds not sure how much information one can get here.

@ptillisch - So far it looks like the map file here is sort of useless? That is it only has the actual code of sketch within it and addressed based from 0. Also I don't believe that the zephyr.map (Built as part of the "bootloader" is included anywhere?). I am running on my own build. Do you know of a good document/post that might describe some of this? Thanks!

However if you can setup to build and install your sketch on Arduino IDE2,
you can have a better chance at looking at your crash locations. That is if you look at the build options:


If you use the default options for Link Mode, you will get similar results for the addresses. However if you use the option value "Static", it no longer links your code through links and the like, which gets redirected during the load of your sketch, instead it is built with real addresses, and if you get a crash you can look at the map file and get better ideas of where that
address is located in your code, or libraries or ...

And likewise maybe where the address you are trying to access might be...

Sorry, I know probably too verbose.

looks like allot of code..
curious, what is the size of the sketch.ino.elf file??
typically located inside of the /.cache/sketch folder for the project..
good luck.. ~q

If you are working in such an environment it has a starting footprint:

Example the simple unchanged "LED blink" software. I think no "Bridge" library
and other stuff is used:

120018   64 -rw-r--r-- 1 arduino arduino   61768 30. MΓ€r 23:27 sketch.ino.elf
120020   68 -rw-r--r-- 1 arduino arduino   66090 30. MΓ€r 23:27 sketch.ino.hex

My code is using a lot of existing libraries:

  • Arduino_RouterBridge 0.4.1
  • Arduino_RPClite 0.2.1
  • ArxContainer 0.7.0
  • ArxTypeTraits 0.3.2
  • DebugLog 0.8.4
  • MsgPack 0.4.2
  • Button2 2.5.0
  • Arduino_Modulino 0.8.0
120966  128 -rw-r--r--  1 arduino arduino  130280 18. Apr 19:54 sketch.ino.elf
120968  140 -rw-r--r--  1 arduino arduino  140993 18. Apr 19:54 sketch.ino.hex

At the end for a STM32 with a flash size of 2 times 1MB the footprint is a don't care.

I work with co-routines (protothreads) so my estimated stack size is in a range of
100...300 Bytes. I do not know how huge the stack of the Zephyr-Arduino main thread is.
But I expect to be far away of using k Bytes. My application itself is using with library
instances inside (Modulino) not more than 1.5 kBytes (STM has >700 k SRAM). I never use malloc()/free() to get memory.

I have made class by class code review with ChatGPT but currently no hint about the crash root-cause. Soon or later I will find the bug.

The best hint has been to look on UART trace to see the core dump :grinning_face: Without the dump you know nothing. Soon or later I will find the bug.

just did a quick check..
the actual file that gets uploaded is sketch.elf-zsk.bin, pretty sure you will find it is the same size..
with core 0.54.1 that file can not be no more than 131072 bytes in size if you are running it from AppLab, you could load it into flash using Arduino IDE..
this was changed in the core just 2 days ago so next release this shouldn't be a limit..
your elf looks like it is under this limit but you are close, is this size with everything or with the offending code commented out??
is the bin file the same size as elf??

~q

119932  128 -rw-r--r--  1 arduino arduino  130556 19. Apr 13:24 sketch.ino.elf
120969  128 -rw-r--r--  1 arduino arduino  130556 19. Apr 13:24 sketch.ino.elf-zsk.bin

What kind of limit are the 131072 bytes? Is the code getting loaded into the SRAM? The MCU has got > 700k SRAM. Zephyr and Arduino libs are using together ~600k SRAM?

Are there documents explaining the limits?

  • Available stack size for the Arduino-Zephyr main thread. I have put a 1024 byte test array onto the stack and it has worked. My stack-less co-routines are not consuming a huge stack. But yes, I have no glue what Arduino code is doing.
  • Available heap for application.
  • Done a carefully malloc and free test (only for testing) to investigate the heap. Has worked.

For embedded programming the STM32U585 is a "big" MCU!

I do not want to work with different IDEs. In need to update on Linux the Python code and the Arduino C++ code in one cycle. If I have investigated the Arduino UNO Q web side I liked the concept to use Linux with Python and the Arduino side in one IDE. And very important, having a powerful embedded MCU on-board, on the same PCB with a communication channel.

Lets see what Arduino/Qualcomm wants to do with the Arduino UNO Q.

yes, into a fixed sized buffer..
changing in the next release to a variable sized buffer..
looks like you are below it so not the issue..

not that I'm aware, only in the source..

and yes, I agree, it is a nice setup, more updates are on the way..

good luck.. ~q

It is the App Lab interface that supports both Python Programming (script) for MPU and Arduino Programming (sketch) for MCU. The IDE supports only the Arduino Programming of the MCU.

If using IDE, then there is a option for sketch loding into Flas/RAM.

If using App Lab, the sketch is always loaded into RAM.

Further investigation revealed that my Arduino application wasn't being loaded correctly into the MCU. The crash occurred before a single line of my code could be executedβ€”likely due to the 132k limit. I waited for the updates (IDE 0.70, etc.), and sure enough, everything now boots without crashing.

big sketch, that's what I was worried about..
i updated today as well too, so far so good..
glad it worked out for you..

code on.. ~q