New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Can't build on OS X for ESP32 #534

Closed
untitledlt opened this Issue Nov 30, 2017 · 16 comments

Comments

Projects
None yet
4 participants
@untitledlt

untitledlt commented Nov 30, 2017

Tried clean install of Atom/Platformio but i'm still getting few warnings like
No hardware SPI pins defined. All SPI access will default to bitbanged output
and always the same non-informative error:

.pioenvs/esp32doit-devkit-v1/lib/libFastLED.a(FastLED.o): In function__cxa_pure_virtual':
/Users/me/workplace/esp32/led-strip/lib/FastLED/FastLED.cpp:243: multiple definition of __cxa_pure_virtual' /Users/me/.platformio/packages/toolchain-xtensa32/bin/../lib/gcc/xtensa-esp32-elf/5.2.0/../../../../xtensa-esp32-elf/lib/li bstdc++.a(pure.o):pure.cc:(.text.__cxa_pure_virtual+0x0): first defined here collect2: error: ld returned 1 exit status *** [.pioenvs/esp32doit-devkit-v1/firmware.elf] Error 1

@focalintent

This comment has been minimized.

Show comment
Hide comment
@focalintent

focalintent Nov 30, 2017

Member

Technically FastLED isn't tested/supported against platformio - it seems that building for the esp8266 w/platformio defines symbols that FastLED has to define when building under arduino. For now you can try commenting out this line in platforms/esp/32/led_sysdefs_esp32.h:

#define NEED_CXX_BITS

Member

focalintent commented Nov 30, 2017

Technically FastLED isn't tested/supported against platformio - it seems that building for the esp8266 w/platformio defines symbols that FastLED has to define when building under arduino. For now you can try commenting out this line in platforms/esp/32/led_sysdefs_esp32.h:

#define NEED_CXX_BITS

@untitledlt

This comment has been minimized.

Show comment
Hide comment
@untitledlt

untitledlt Dec 1, 2017

Great! That helped and i was able to compile it.
But it still have some issues. I'm using Blink example as per https://github.com/FastLED/FastLED/blob/master/examples/Blink/Blink.ino, it compiles successfully but it looks like FastLED lib breaks delay functionality on main loop. I've added Serial.print after FastLED.show(); and i can see output on a serial console with a zero delay.

EDIT: i've found related issue #366
Am i right, that it wasn't fixed and possibly won't be any time soon?

untitledlt commented Dec 1, 2017

Great! That helped and i was able to compile it.
But it still have some issues. I'm using Blink example as per https://github.com/FastLED/FastLED/blob/master/examples/Blink/Blink.ino, it compiles successfully but it looks like FastLED lib breaks delay functionality on main loop. I've added Serial.print after FastLED.show(); and i can see output on a serial console with a zero delay.

EDIT: i've found related issue #366
Am i right, that it wasn't fixed and possibly won't be any time soon?

@focalintent

This comment has been minimized.

Show comment
Hide comment
@focalintent

focalintent Dec 1, 2017

Member

Are you disabling interrupts or not? #366 is only an issue when interrupts are being disabled.

Also @samguyer - are you aware of any issues w/esp32's and delay?

Member

focalintent commented Dec 1, 2017

Are you disabling interrupts or not? #366 is only an issue when interrupts are being disabled.

Also @samguyer - are you aware of any issues w/esp32's and delay?

@samguyer

This comment has been minimized.

Show comment
Hide comment
@samguyer

samguyer Dec 1, 2017

Contributor

We need to add a condition to the definition of __cxa_pure_virtual. Currently, it is only excluded for the ESP8266, but it should also be excluded for ESP32. Here's the relevant code in FastLED.cpp:

#ifdef NEED_CXX_BITS
namespace __cxxabiv1
{
        #ifndef ESP8266
        extern "C" void __cxa_pure_virtual (void) {}
        #endif
Contributor

samguyer commented Dec 1, 2017

We need to add a condition to the definition of __cxa_pure_virtual. Currently, it is only excluded for the ESP8266, but it should also be excluded for ESP32. Here's the relevant code in FastLED.cpp:

#ifdef NEED_CXX_BITS
namespace __cxxabiv1
{
        #ifndef ESP8266
        extern "C" void __cxa_pure_virtual (void) {}
        #endif
@samguyer

This comment has been minimized.

Show comment
Hide comment
@samguyer

samguyer Dec 1, 2017

Contributor

@untitledlt Which version of the ESP32 support are you using? The current head disables interrupts, which breaks the delay function by ignoring the timer interrupt. Try adding my pull request that uses the RMT peripheral.

Contributor

samguyer commented Dec 1, 2017

@untitledlt Which version of the ESP32 support are you using? The current head disables interrupts, which breaks the delay function by ignoring the timer interrupt. Try adding my pull request that uses the RMT peripheral.

@untitledlt

This comment has been minimized.

Show comment
Hide comment
@untitledlt

untitledlt Dec 5, 2017

@focalintent i'm not disabling any interrupts. I'm using Blink example without any modifications.

@samguyer what do you mean by version of the ESP32 support?
I'm using ESP32-WROOM-32 DoIt DevKit v1, if that's what are you asking for.

untitledlt commented Dec 5, 2017

@focalintent i'm not disabling any interrupts. I'm using Blink example without any modifications.

@samguyer what do you mean by version of the ESP32 support?
I'm using ESP32-WROOM-32 DoIt DevKit v1, if that's what are you asking for.

@samguyer

This comment has been minimized.

Show comment
Hide comment
@samguyer

samguyer Dec 5, 2017

Contributor

@untitledlt Sorry, my message was confusing. There is an experimental branch of FastLED that implements a different way of sending out the bits on the ESP32. Try this version out:

https://github.com/samguyer/FastLED

I included the fix for __cxa_pure_virtual, so you shouldn't need to worry about that problem.

Contributor

samguyer commented Dec 5, 2017

@untitledlt Sorry, my message was confusing. There is an experimental branch of FastLED that implements a different way of sending out the bits on the ESP32. Try this version out:

https://github.com/samguyer/FastLED

I included the fix for __cxa_pure_virtual, so you shouldn't need to worry about that problem.

@BlackEdder

This comment has been minimized.

Show comment
Hide comment
@BlackEdder

BlackEdder Dec 21, 2017

@samguyer Can I still use the same GPIO pin as data_pin, or do I need to choose a specific pin with your version on the ESP32

BlackEdder commented Dec 21, 2017

@samguyer Can I still use the same GPIO pin as data_pin, or do I need to choose a specific pin with your version on the ESP32

@samguyer

This comment has been minimized.

Show comment
Hide comment
@samguyer

samguyer Dec 21, 2017

Contributor

@BlackEdder You can choose any pin that supports digital output and is not delegated to some specific task. One constraint is the ESP32 itself. Certain pins are input-only (34-39), and others are dedicated to specific tasks (6-11 for flash memory access). In addition, it is not easy to use pins above 31 because of the way FastLED represents information about pins. I have tried to encode these constraints the in fastpin_esp32.h file, so that FastLED will give you a compile error if you try to use a pin that will not work.

Short version: I have used a bunch of different pins on the ESP32, including 12, 14, 16, 17, 18.
I like this diagram (although it doesn't tell you that 34-39 are input only):

https://raw.githubusercontent.com/gojimmypi/ESP32/master/images/myESP32%20DevKitC%20pinout.png

Contributor

samguyer commented Dec 21, 2017

@BlackEdder You can choose any pin that supports digital output and is not delegated to some specific task. One constraint is the ESP32 itself. Certain pins are input-only (34-39), and others are dedicated to specific tasks (6-11 for flash memory access). In addition, it is not easy to use pins above 31 because of the way FastLED represents information about pins. I have tried to encode these constraints the in fastpin_esp32.h file, so that FastLED will give you a compile error if you try to use a pin that will not work.

Short version: I have used a bunch of different pins on the ESP32, including 12, 14, 16, 17, 18.
I like this diagram (although it doesn't tell you that 34-39 are input only):

https://raw.githubusercontent.com/gojimmypi/ESP32/master/images/myESP32%20DevKitC%20pinout.png

@BlackEdder

This comment has been minimized.

Show comment
Hide comment
@BlackEdder

BlackEdder Dec 21, 2017

@samguyer Great, this version sorts out some flickering issues I had. The only thing is that it now sometimes goes crazy. I have it set up so I can change the pattern through a webpage (using ESPAsyncWebServer). This always worked fine, but it sometimes goes crazy when I do that. Should I ALLOW_INTERRUPTS? Could that solve it?

BlackEdder commented Dec 21, 2017

@samguyer Great, this version sorts out some flickering issues I had. The only thing is that it now sometimes goes crazy. I have it set up so I can change the pattern through a webpage (using ESPAsyncWebServer). This always worked fine, but it sometimes goes crazy when I do that. Should I ALLOW_INTERRUPTS? Could that solve it?

@samguyer

This comment has been minimized.

Show comment
Hide comment
@samguyer

samguyer Dec 21, 2017

Contributor

@BlackEdder I don't think that will help. The RMT implementation does not disable interrupts at all (because it doesn't need to). BUT it could certainly be the case that a high-priority interrupt from some other source (like the WiFi stack) disrupts the process of driving the RMT device. I'll take a look at what should happen in that case.

One thing you could try is force your FastLED code to run on a different core from the WiFi handling code. Take a look at the xTaskCreate function in the ESP core (the FreeRTOS API). I don't remember the exact parameters to use, but you can force a function to execute on a particular core. You can also find out where code is running by calling xPortGetCoreID(). You'll get either 0 or 1 (core 0 or core 1).

Let me know what works, so that I can pass advice on to other people!

Contributor

samguyer commented Dec 21, 2017

@BlackEdder I don't think that will help. The RMT implementation does not disable interrupts at all (because it doesn't need to). BUT it could certainly be the case that a high-priority interrupt from some other source (like the WiFi stack) disrupts the process of driving the RMT device. I'll take a look at what should happen in that case.

One thing you could try is force your FastLED code to run on a different core from the WiFi handling code. Take a look at the xTaskCreate function in the ESP core (the FreeRTOS API). I don't remember the exact parameters to use, but you can force a function to execute on a particular core. You can also find out where code is running by calling xPortGetCoreID(). You'll get either 0 or 1 (core 0 or core 1).

Let me know what works, so that I can pass advice on to other people!

@samguyer

This comment has been minimized.

Show comment
Hide comment
@samguyer

samguyer Dec 21, 2017

Contributor

@BlackEdder Another option that @kriegsman suggested to me is to wrap the FastLED show() function in a call to xTaskCreate, so that every call to show is spawned onto the other core. That strategy avoids all the pain of synchronizing between two cores (race conditions, deadlocks, etc). As long as the overhead of xTaskCreate is low (which it should be), this strategy should work great with very little change to your code.

Contributor

samguyer commented Dec 21, 2017

@BlackEdder Another option that @kriegsman suggested to me is to wrap the FastLED show() function in a call to xTaskCreate, so that every call to show is spawned onto the other core. That strategy avoids all the pain of synchronizing between two cores (race conditions, deadlocks, etc). As long as the overhead of xTaskCreate is low (which it should be), this strategy should work great with very little change to your code.

@samguyer

This comment has been minimized.

Show comment
Hide comment
@samguyer

samguyer Dec 21, 2017

Contributor

Something like the code below. I need to look up how to pin the task to a particular core, and how to make sure the "show" task is complete before continuing.

void doShow(void * parameter) 
{
    FastLED.show();
}

void showESP32()
{
        xTaskCreate(
                doShow(),                 // Task function. 
                "show on ESP32",     // String with name of task. 
                10000,             // Stack size in words. 
                NULL,              // Parameter passed as input of the task 
                10,                  // Priority of the task. 
                NULL);             // Task handle.
}

void myLights()
{
    while (1) {
        renderLights();
        showESP32();
        delay(50);
    }
}
Contributor

samguyer commented Dec 21, 2017

Something like the code below. I need to look up how to pin the task to a particular core, and how to make sure the "show" task is complete before continuing.

void doShow(void * parameter) 
{
    FastLED.show();
}

void showESP32()
{
        xTaskCreate(
                doShow(),                 // Task function. 
                "show on ESP32",     // String with name of task. 
                10000,             // Stack size in words. 
                NULL,              // Parameter passed as input of the task 
                10,                  // Priority of the task. 
                NULL);             // Task handle.
}

void myLights()
{
    while (1) {
        renderLights();
        showESP32();
        delay(50);
    }
}
@samguyer

This comment has been minimized.

Show comment
Hide comment
@samguyer

samguyer Dec 21, 2017

Contributor

OK, the function you want is xTaskCreatePinnedToCore. It's the same as xTaskCreate, but takes an extra argument that is the core ID.

Contributor

samguyer commented Dec 21, 2017

OK, the function you want is xTaskCreatePinnedToCore. It's the same as xTaskCreate, but takes an extra argument that is the core ID.

@BlackEdder

This comment has been minimized.

Show comment
Hide comment
@BlackEdder

BlackEdder Dec 22, 2017

@samguyer Thank you for all the help. I'll try to test that out and report back 👍

BlackEdder commented Dec 22, 2017

@samguyer Thank you for all the help. I'll try to test that out and report back 👍

@BlackEdder

This comment has been minimized.

Show comment
Hide comment
@BlackEdder

BlackEdder Dec 22, 2017

Note though that AsyncTCP (used by ESPAsyncWebServer) also pins a TCP reading task to the second core, so that might cause problems? I think all TCP handling is in general done on the second core for the ESP32.

BlackEdder commented Dec 22, 2017

Note though that AsyncTCP (used by ESPAsyncWebServer) also pins a TCP reading task to the second core, so that might cause problems? I think all TCP handling is in general done on the second core for the ESP32.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment