<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[M5Atom S3 Exception LoadProhibited if dead code is present]]></title><description><![CDATA[<p dir="auto">I am experiencing a odd behavior with my code, which I am not able to solve by myself. I'm using platformio to implement and upload code to my Atom S3.</p>
<p dir="auto">I have following code which first waits for a BLE connection and then sends/receives information.</p>
<pre><code>#include &lt;M5AtomS3.h&gt;
#include &lt;Preferences.h&gt;
#include &lt;M5Unified.h&gt;
#include &lt;NimBLEDevice.h&gt;
#include "Buttons.cpp"

#define SERVICE_UUID *HIDDEN*
#define CHARACTERISTIC_UUID *HIDDEN*

#define DEBUG
// Debugging helper for Serial connection
#ifdef DEBUG
#define PRINTF(text, ...) Serial.printf(text, __VA_ARGS__)
#define PRINTLN(text) Serial.println(text)
#define PRINT(text) Serial.print(text)
#else
#define PRINTF(text, ...)
#define PRINTLN(text)
#define PRINT(text)
#endif

using namespace std;

NimBLEServer *pServer;
NimBLECharacteristic *pCharacteristic;
M5Canvas canvas(&amp;AtomS3.Display);
LGFX_Button button;
Preferences preferences;

// Parameters
auto *font = &amp;fonts::DejaVu18;
unsigned int counter;
int offset_from_top = 5;
const char *games_counter_key = "games";

// BLE Commands
const string recording_prefix = "recording:";
const string ready_prefix = "ready:";

const string cmd_rec = "REC";
const string cmd_stop = "STOP";

// Placeholder for recording timestamp
string time_label = "";

// State machine
enum pi_state
{
    disconnected = 1,
    connected = 2,
    recording = 3,
};
pi_state p_s = disconnected;

volatile bool update = false;

// Button Bitmaps
extern const unsigned short rec_inactive[];
extern const unsigned short rec_unpressed[];
extern const unsigned short rec_pressed[];
extern const unsigned short stop_unpressed[];
extern const unsigned short stop_pressed[];

// BLE Callbacks
class MyServerCallbacks : public NimBLEServerCallbacks
{
    void onConnect(NimBLEServer *pServer)
    {
        // p_s = connected;
        PRINT("Client connected!\n");
    }

    void onDisconnect(NimBLEServer *pServer)
    {
        p_s = disconnected;
        PRINT("Client disconnected.\n");
    }
};

class MyCharacteristicCallbacks : public NimBLECharacteristicCallbacks
{
    void onWrite(NimBLECharacteristic *pCharacteristic)
    {
        update = true;
    }
};

void put_asleep()
{
    M5.Display.sleep();
    M5.Display.waitDisplay();
    gpio_get_level(GPIO_NUM_41);
    gpio_wakeup_enable((GPIO_NUM_41),GPIO_INTR_LOW_LEVEL);
    esp_sleep_enable_gpio_wakeup();
    NimBLEDevice::stopAdvertising();
    Serial.print("Sleepy\n");
    esp_light_sleep_start();
    // Start from the beginning... will return excp in Serial
    esp_restart();
}

void setup()
{
    auto cfg = M5.config();
#if defined(DEBUG)
    cfg.serial_baudrate = 115200;
#endif
    AtomS3.begin(cfg);
    preferences.begin(
        "my-app",
        false);

    counter = preferences.getUInt(
        games_counter_key,
        0);
    PRINTF("Counter: %d\n", counter);
    if (AtomS3.Display.isEPD())
    {
        AtomS3.Display.setEpdMode(epd_mode_t::epd_fastest);
    }
    canvas.setColorDepth(16);
    canvas.createSprite(AtomS3.Display.width(),
                        AtomS3.Display.height());
    canvas.setTextColor(WHITE);
    canvas.setTextDatum(middle_centre);
    canvas.setFont(font);
    canvas.setTextSize(0.9f);
    offset_from_top = (canvas.fontHeight(font) / 2) + 2;

    int edge_length = canvas.height() - (canvas.fontHeight(font) * 2) - 15;
    button.initButton(&amp;canvas, canvas.width() / 2, canvas.height() / 2 + (canvas.fontHeight(font)) + 4, edge_length, edge_length, TFT_LIGHTGREY, TFT_DARKGREY, TFT_BLACK, "");

    NimBLEDevice::init("Kicker_GATT_Server");

    pServer = NimBLEDevice::createServer();
    pServer-&gt;setCallbacks(new MyServerCallbacks());

    NimBLEService *pService = pServer-&gt;createService(SERVICE_UUID);

    pCharacteristic = pService-&gt;createCharacteristic(
        CHARACTERISTIC_UUID,
        NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::NOTIFY);

    pCharacteristic-&gt;setCallbacks(new MyCharacteristicCallbacks());
    pCharacteristic-&gt;setValue("Hello GATT!");

    pService-&gt;start();
    NimBLEDevice::startAdvertising();

    canvas.drawString("Stats", canvas.width() / 2, offset_from_top);
    canvas.drawString("Games played:", canvas.width() / 2, canvas.height() / 2 - (canvas.fontHeight(font) / 2) - 2);
    canvas.drawNumber(counter, canvas.width() / 2, canvas.height() / 2 + (canvas.fontHeight(font) / 2) + 2, &amp;fonts::DejaVu24);
    canvas.pushSprite(0, 0);
    delay(3000);

    PRINTLN("Setup done");
}

void loop()
{
    if(update){
        std::string value = pCharacteristic-&gt;getValue().c_str();

        PRINTF("Received data: \"%s\"\n", value.c_str());

        if (value.compare(0, recording_prefix.length(), recording_prefix) == 0)
        {
            if (p_s == connected)
            {
                counter++;
                preferences.putUInt(
                    games_counter_key,
                    counter);
            }
            canvas.fillRect(0, offset_from_top + canvas.fontHeight(font) * 2 + 2, canvas.width(), canvas.height(), TFT_BLACK);
            canvas.pushImage(canvas.width() / 2 - 40, canvas.height() / 2 + (canvas.fontHeight(font)) + 4 - 40, 80, 80, (uint16_t *)stop_unpressed);
            p_s = recording;
            if (value.length() &gt; 10)
                time_label = value.substr(recording_prefix.length());
        }
        else if (value.compare(0, ready_prefix.length(), ready_prefix) == 0)
        {
            canvas.fillRect(0, offset_from_top + canvas.fontHeight(font) * 2 + 2, canvas.width(), canvas.height(), TFT_BLACK);
            canvas.pushImage(canvas.width() / 2 - 40, canvas.height() / 2 + (canvas.fontHeight(font)) + 4 - 40, 80, 80, (uint16_t *)rec_unpressed);
            p_s = connected;
            time_label = "";
        }
        update = false;
    }
    AtomS3.update();
    switch (p_s)
    {
    case connected:
        canvas.fillRect(0, 0, canvas.width(), offset_from_top + canvas.fontHeight(font) * 2 + 2, TFT_BLACK);
        canvas.drawString("Press to", canvas.width() / 2, offset_from_top);
        canvas.drawString("record", canvas.width() / 2, offset_from_top + canvas.fontHeight(font) + 2);
        if (AtomS3.BtnA.isHolding() || AtomS3.BtnA.wasPressed())
        {
            canvas.fillRect(0, offset_from_top + canvas.fontHeight(font) * 2 + 2, canvas.width(), canvas.height(), TFT_BLACK);
            canvas.pushImage(canvas.width() / 2 - 40, canvas.height() / 2 + (canvas.fontHeight(font)) + 4 - 40, 80, 80, (uint16_t *)rec_pressed);
            PRINTLN("Pressed");
        }
        if (AtomS3.BtnA.wasReleased())
        {
            canvas.fillRect(0, offset_from_top + canvas.fontHeight(font) * 2 + 2, canvas.width(), canvas.height(), TFT_BLACK);
            canvas.pushImage(canvas.width() / 2 - 40, canvas.height() / 2 + (canvas.fontHeight(font)) + 4 - 40, 80, 80, (uint16_t *)rec_unpressed);

            pCharacteristic-&gt;setValue(cmd_rec);
            pCharacteristic-&gt;notify();

            PRINTLN("Released");
        }
        break;

    case recording:
        canvas.fillRect(0, 0, canvas.width(), offset_from_top + canvas.fontHeight(font) * 2 + 2, TFT_BLACK);
        canvas.drawString("Recording", canvas.width() / 2, offset_from_top);
        canvas.drawString(time_label.c_str(), canvas.width() / 2, offset_from_top + canvas.fontHeight(font) + 2);
        if (AtomS3.BtnA.isHolding() || AtomS3.BtnA.wasPressed())
        {
            canvas.fillRect(0, offset_from_top + canvas.fontHeight(font) * 2 + 2, canvas.width(), canvas.height(), TFT_BLACK);
            canvas.pushImage(canvas.width() / 2 - 40, canvas.height() / 2 + (canvas.fontHeight(font)) + 4 - 40, 80, 80, (uint16_t *)stop_pressed);

            PRINTLN("Pressed");
        }
        if (AtomS3.BtnA.wasReleased())
        {
            canvas.fillRect(0, offset_from_top + canvas.fontHeight(font) * 2 + 2, canvas.width(), canvas.height(), TFT_BLACK);
            canvas.pushImage(canvas.width() / 2 - 40, canvas.height() / 2 + (canvas.fontHeight(font)) + 4 - 40, 80, 80, (uint16_t *)stop_unpressed);
            pCharacteristic-&gt;setValue(cmd_stop);
            pCharacteristic-&gt;notify();

            PRINTLN("Released");
        }
        break;

    default:
        canvas.fillRect(0, 0, canvas.width(), offset_from_top + canvas.fontHeight(font) * 2 + 2, TFT_BLACK);
        canvas.drawString("Disconnected", canvas.width() / 2, offset_from_top);
        canvas.drawString("Waiting for Pi", canvas.width() / 2, offset_from_top + canvas.fontHeight(font) + 2);
        canvas.fillRect(0, offset_from_top + canvas.fontHeight(font) * 2 + 2, canvas.width(), canvas.height(), TFT_BLACK);
        canvas.pushImage(canvas.width() / 2 - 40, canvas.height() / 2 + (canvas.fontHeight(font)) + 4 - 40, 80, 80, (uint16_t *)rec_inactive);
        break;
    }
    canvas.pushSprite(0, 0);
}
</code></pre>
<p dir="auto"><code>Buttons.cpp</code> only contains images in binary format. <code>put_asleep()</code> is dead code but will become relevant in a few seconds. It's just some random code I've used to test other things and features, which led me to the issue in the first place.</p>
<p dir="auto">If I run this code, I will get the following exception once a BLE connection is established and first informations should be displayed (line 196 is the line starting with <code>canvas.drawString("record"...</code> in the first switch case block.</p>
<pre><code>Guru Meditation Error: Core  1 panic'ed (LoadProhibited). Exception was unhandled.

Core  1 register dump:
PC      : 0x42003e62  PS      : 0x00060630  A0      : 0x8201d918  A1      : 0x3fcebe40  
A2      : 0x3fc9d4b4  A3      : 0x3fc98730  A4      : 0x3fc9872c  A5      : 0x00000040  
A6      : 0x00000000  A7      : 0x00000080  A8      : 0x82003e60  A9      : 0x3fcebe20  
A10     : 0x00000036  A11     : 0x3c07029e  A12     : 0x00000040  A13     : 0x0000001c  
A14     : 0x0000002c  A15     : 0x00000000  SAR     : 0x00000010  EXCCAUSE: 0x0000001c  
EXCVADDR: 0x00000018  LBEG    : 0x400570a4  LEND    : 0x400570a9  LCOUNT  : 0x00000000  


Backtrace: 0x42003e5f:0x3fcebe40 0x4201d915:0x3fcebeb0
  #0  0x42003e5f in loop() at src/main.cpp:196
  #1  0x4201d915 in loopTask(void*) at /Users/xyz/.platformio/packages/framework-arduinoespressif32/cores/esp32/main.cpp:50





ELF file SHA256: c74994da80137adc

Rebooting...
ESP-ROM:esp32s3-20210327
Build:Mar 27 2021
rst:0xc (RTC_SW_CPU_RST),boot:0x28 (SPI_FAST_FLASH_BOOT)
Saved PC:0x420663d6
  #0  0x420663d6 in esp_pm_impl_waiti at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/esp_pm/pm_impl.c:855
</code></pre>
<p dir="auto">I am already aware that this indicates some sort of null pointer problem. However, the corresponding line does not have a null pointer (at least from my understanding). <code>canvas</code> is used in the line before, without any issue. The problem still persists if I remove the font height getter. Also, the stack trace will simply point to the next line, if I comment out line 196.<br />
The weirdest part here is, that if <code>put_asleep()</code> is removed or commented out, the exception does <strong>not</strong> occur. The issue persists regardless of its content. Especially this aspect makes me wonder what the underlying issue is. I've changed the overall code a lot, while trying to solve it, but I'm out of ideas now.</p>
<p dir="auto">Does somehow have any clue what the problem/error here is?</p>
]]></description><link>https://community.m5stack.com/topic/7165/m5atom-s3-exception-loadprohibited-if-dead-code-is-present</link><generator>RSS for Node</generator><lastBuildDate>Sat, 09 May 2026 03:36:49 GMT</lastBuildDate><atom:link href="https://community.m5stack.com/topic/7165.rss" rel="self" type="application/rss+xml"/><pubDate>Mon, 06 Jan 2025 16:58:08 GMT</pubDate><ttl>60</ttl><item><title><![CDATA[Reply to M5Atom S3 Exception LoadProhibited if dead code is present on Wed, 08 Jan 2025 09:59:28 GMT]]></title><description><![CDATA[<p dir="auto">Hey <a class="plugin-mentions-user plugin-mentions-a" href="/user/felmue" aria-label="Profile: felmue">@<bdi>felmue</bdi></a>,</p>
<p dir="auto">thanks, this did solve all the issues! Didn't know that I can solely rely on the Unified library without any further changes.<br />
Do you know if this is intended, and if so, why does the Board-specific library exist?</p>
<p dir="auto">Thank you so much for your help!</p>
]]></description><link>https://community.m5stack.com/post/27810</link><guid isPermaLink="true">https://community.m5stack.com/post/27810</guid><dc:creator><![CDATA[nelll]]></dc:creator><pubDate>Wed, 08 Jan 2025 09:59:28 GMT</pubDate></item><item><title><![CDATA[Reply to M5Atom S3 Exception LoadProhibited if dead code is present on Wed, 08 Jan 2025 08:12:25 GMT]]></title><description><![CDATA[<p dir="auto">Hello <a class="plugin-mentions-user plugin-mentions-a" href="/user/nelll" aria-label="Profile: nelll">@<bdi>nelll</bdi></a></p>
<p dir="auto">have you tried to not use M5AtomS3 library and only use M5Unified library and replace all <code>AtomS3.</code> with <code>M5.</code>? Note: not tested myself - just an idea.</p>
<p dir="auto">Thanks<br />
Felix</p>
]]></description><link>https://community.m5stack.com/post/27809</link><guid isPermaLink="true">https://community.m5stack.com/post/27809</guid><dc:creator><![CDATA[felmue]]></dc:creator><pubDate>Wed, 08 Jan 2025 08:12:25 GMT</pubDate></item><item><title><![CDATA[Reply to M5Atom S3 Exception LoadProhibited if dead code is present on Tue, 07 Jan 2025 16:19:08 GMT]]></title><description><![CDATA[<p dir="auto">Hi <a class="plugin-mentions-user plugin-mentions-a" href="/user/felmue" aria-label="Profile: felmue">@<bdi>felmue</bdi></a></p>
<p dir="auto">thank you for your help!</p>
<p dir="auto">This solves the issue in the mentioned example.<br />
However, I took a look at an earlier version of my code and this issue persists if I add <code>AtomS3.Power.deepSleep(0,false);</code> or <code>M5.Power.deepSleep(0,false);</code> somewhere. This was the reason for the messy implementation of <code>put_asleep</code> as a workaround in the first place. I've checked it with the code above and if you replace the content of <code>put_asleep</code> with just the <code>deepSleep</code> call, it still runs into the exception. Same applies to <code>lightSleep</code>.</p>
<p dir="auto">I assume the reason behind this, is the fact, that the AtomS3 library contains calls to the Unified library (<code>M5.(...)</code>)?!</p>
<p dir="auto">Nonetheless, from my understanding, it has to be some mistake I must have made, because otherwise this problem would have happened to other devs as well, as this is pretty significant. However, I'm out of ideas with my limited knowledge about C++ and ESP overall.</p>
<p dir="auto">P.S.: I've removed the redundant <code>#include &lt;M5Unified.h&gt;</code>. Still the same issues...</p>
]]></description><link>https://community.m5stack.com/post/27793</link><guid isPermaLink="true">https://community.m5stack.com/post/27793</guid><dc:creator><![CDATA[nelll]]></dc:creator><pubDate>Tue, 07 Jan 2025 16:19:08 GMT</pubDate></item><item><title><![CDATA[Reply to M5Atom S3 Exception LoadProhibited if dead code is present on Tue, 07 Jan 2025 10:13:53 GMT]]></title><description><![CDATA[<p dir="auto">Hello <a class="plugin-mentions-user plugin-mentions-a" href="/user/nelll" aria-label="Profile: nelll">@<bdi>nelll</bdi></a></p>
<p dir="auto">it looks like the crash is happening when <code>AtomS3.BtnA.isHolding()</code> is called.</p>
<p dir="auto">Now the strange part. When I modify below two lines in <code>put_asleep()</code> the crash goes away.</p>
<pre><code>//    M5.Display.sleep();
//    M5.Display.waitDisplay();
    AtomS3.Display.sleep();
    AtomS3.Display.waitDisplay();
</code></pre>
<p dir="auto">I can only guess that while <code>put_asleep()</code> isn't called anywhere it still confuses somehow the namespaces - but that is really just a wild guess.</p>
<p dir="auto">Thanks<br />
Felix</p>
]]></description><link>https://community.m5stack.com/post/27789</link><guid isPermaLink="true">https://community.m5stack.com/post/27789</guid><dc:creator><![CDATA[felmue]]></dc:creator><pubDate>Tue, 07 Jan 2025 10:13:53 GMT</pubDate></item></channel></rss>