Skip to content
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

#include "arduino_freertos.h" breaks other libraries that use the arduino namespace #22

Closed
yamaan93 opened this issue Oct 7, 2023 · 3 comments

Comments

@yamaan93
Copy link

yamaan93 commented Oct 7, 2023

I'm working on a project that requires an RTOS and the FlexCAN_T4 library, and I noticed some strange behaviour with the library. First I tried just adding freetos-teensy to my lib_deps and manually importing the headers and setting up freeRTOS tasks but I noticed when i did things that way, my program only worked if I had the serial monitor open. I messed around with it for some time, and wasn't making any progress, so I removed my program entirely, copied the blink example from this library, and that proceeded to work without the serial monitor open, so I told myself I'd just start from this example instead and went to move over my CAN bus usage. However, after adding declaring my FlexCAN object, the program wouldn't compile since the FlexCAN library uses many of the arduino namespace defines and I get this kind of error:
I'm working on a project that requires an RTOS and the FlexCAN_T4 library, and I noticed some strange behaviour with the library. First I tried just adding freetos-teensy to my lib_deps and manually importing the headers and setting up freeRTOS tasks but I noticed when i did things that way, my program only worked if I had the serial monitor open. I messed around with it for some time, and wasn't making any progress, so I removed my program entirely, copied the blink example from this library, and that proceeded to work without the serial monitor open, so I told myself I'd just start from this example instead and went to move over my CAN bus usage. However, after adding declaring my FlexCAN object, the program wouldn't compile since the FlexCAN library uses many of the arduino namespace defines and I get this kind of error:

.pio\libdeps\teensy41\FlexCAN_T4/FlexCAN_T4FD.tpp:810:53: error: 'HEX' was not declared in this scope; did you mean 'arduino::HEX'?

Here is my original program where I didn't have issues compiling, but the program wouldn't work unless the serial monitor was open:

#include <Arduino.h>
#include <FlexCAN_T4.h>
#include "arduino_freertos.h"
#include "avr/pgmspace.h"

FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> Can0;


// put function declarations here:
void canSniff(const CAN_message_t &msg);
static void task1(void*);

void setup() {
  Serial.begin(250000);
  Can0.begin();
  Can0.setBaudRate(500000);
  Can0.setMaxMB(64);
  Can0.enableFIFO();
  Can0.enableMBInterrupt(FIFO);
  Can0.enableFIFOInterrupt();
  Can0.onReceive(canSniff);
  pinMode(arduino::LED_BUILTIN, arduino::OUTPUT);
  if (CrashReport) {
        ::Serial.print(CrashReport);
        ::Serial.println();
        ::Serial.flush();
    }
  Serial.println(PSTR("\r\nBooting FreeRTOS kernel " tskKERNEL_VERSION_NUMBER ". Built by gcc " __VERSION__ " (newlib " _NEWLIB_VERSION ") on " __DATE__ ". ***\r\n"));
  xTaskCreate(task1, "task1", 128, nullptr, 2, nullptr);
  Serial.println("setup(): starting scheduler...");
  vTaskStartScheduler();

}

void loop() {
 
}
void canSniff(const CAN_message_t &msg) {
  Serial.print(msg.id);
  Serial.print(" ");
  for ( uint8_t i = 0; i < msg.len; i++ ) {
    Serial.print(msg.buf[i]); Serial.print(" ");
  } Serial.println();
}


static void task1(void*) {
    while (true) {
        ::digitalWriteFast(arduino::LED_BUILTIN, arduino::LOW);
        ::vTaskDelay(pdMS_TO_TICKS(500));

        ::digitalWriteFast(arduino::LED_BUILTIN, arduino::HIGH);
        ::vTaskDelay(pdMS_TO_TICKS(500));
    }
}

and here is the program in which it refuses to compile due to namespace issues (just the blink example with my object declaration added):


#include "arduino_freertos.h"
#include "Arduino.h"
#include <FlexCAN_T4.h>
#include "avr/pgmspace.h"


namespace arduino{
    FlexCAN_T4<CAN3, RX_SIZE_256, TX_SIZE_16> Can0;
}


static void task1(void*) {
    while (true) {
        ::digitalWriteFast(arduino::LED_BUILTIN, arduino::LOW);
        ::vTaskDelay(pdMS_TO_TICKS(500));

        ::digitalWriteFast(arduino::LED_BUILTIN, arduino::HIGH);
        ::vTaskDelay(pdMS_TO_TICKS(500));
    }
}

static void task2(void*) {
    while (true) {
        ::Serial.println("TICK");
        ::vTaskDelay(pdMS_TO_TICKS(1'000));

        ::Serial.println("TOCK");
        ::vTaskDelay(pdMS_TO_TICKS(1'000));
    }
}

FLASHMEM __attribute__((noinline)) void setup() {
    ::Serial.begin(250000);
    ::pinMode(arduino::LED_BUILTIN, arduino::OUTPUT);
    ::digitalWriteFast(arduino::LED_BUILTIN, arduino::HIGH);

    ::delay(5'000);

    if (CrashReport) {
        ::Serial.print(CrashReport);
        ::Serial.println();
        ::Serial.flush();
    }

    ::Serial.println(PSTR("\r\nBooting FreeRTOS kernel " tskKERNEL_VERSION_NUMBER ". Built by gcc " __VERSION__ " (newlib " _NEWLIB_VERSION ") on " __DATE__ ". ***\r\n"));

    ::xTaskCreate(task1, "task1", 128, nullptr, 2, nullptr);
    ::xTaskCreate(task2, "task2", 128, nullptr, 2, nullptr);

    ::Serial.println("setup(): starting scheduler...");
    ::Serial.flush();

    ::vTaskStartScheduler();
}

void loop() {}
@tsandmann
Copy link
Owner

Add #define USE_ARDUINO_DEFINES before #include "arduino_freertos.h" to provide the global Arduino defines needed by the library.

I've never used the CAN library, so this is just a guess, but avoid doing the CAN driver initialization before calling vTaskStartScheduler(), this may cause the other error.

@yamaan93
Copy link
Author

yamaan93 commented Oct 7, 2023

I tried adding a -DUSE_ARDUINO_DEFINES to my build flags, however that just gave me a bunch of weird syntax errors, however,
I found that including <Arduino.h> and <FlexCAN_T4.h> before #include "arduino_freertos.h" and #include "avr/pgmspace.h" fixes the name space issue, then -DUSE_ARDUINO_DEFINES let me go back to using the arduino defines without arduino:: everywhere in the program.

The second program worked for that reason, and the issue with the serial monitor seems to have something to do with how this FreeRTOS port handles Serial.print(), as it deadlocks the program if it's put inside an ISR. I just added #define Serial if(Serial)Serial to the top of my program to get around this for now since I'm just using serial print for debug statements for now. Is there a better thread-safe way to print using this library?

Thanks

@tsandmann
Copy link
Owner

I think you must not use Teensy's Serial in an ISR.

This library doesn't come with any peripheral drivers for FreeRTOS, so you need to add a mutex or semaphore to make Serial or any other global instance from Arduino thread-safe.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants