Static link to std::thread seems missing

Hi,

I have an application for my photon which basically boils down it communicating to two one wire devices. In order two read them out in parallel I would like to run one of them in a separated thread. For this case I would like to read out two DS20B18 temp sensors.

The main file looks like this:

#include "temp.h"
temp ds = temp();
void setup() {
    ds.setup();
}
void loop () {
delay(100);
ds.read();
}

And the class header file:

#ifndef TEMP_H
#define TEMP_H

#include "application.h"
#include "OneWire/OneWire.h"
#include <atomic>
#include <thread>

#define TEMP_PIN D6
#define N_TEMP 2

void read_thread(std::atomic<uint32_t> *packed_value) {
    // The temperature readout all takes place in an other thread
    // The packed value are two temperatures each 16 times the value
    // °C when representing them as byte
    byte addr[N_TEMP][8];
    OneWire ds = OneWire(TEMP_PIN);
    
    ds.search(addr[0]);
    ds.search(addr[1]);
    
    for (;;) {
	uint32_t tmp_pack = 0;
	for (uint8_t i=0; i < N_TEMP; i++) {
	    ds.reset();
	    ds.select(addr[i]);
	    ds.write(0x44, 1); // start conversion
	    delay(1000); // 750ms minimum
    
	    ds.reset();
	    ds.select(addr[i]);
	    ds.write(0xBE); // Read Scratchpad
    
	    byte insign_byte = ds.read();
	    byte sign_byte = ds.read();
	    
	    tmp_pack <<= 16;
	    tmp_pack |= (sign_byte << 8) | insign_byte;
	}
	*packed_value = tmp_pack;
    }
    delay(1000 * 60); // It's enough to read it out every minute or so
}


class temp {
    public:
	temp() {
	    // The reading of the temperature sensor takes places on an other thread
	    Particle.variable("Temp", txt_value);
	    pack = new std::atomic<uint32_t>(0);
	}
	
	void setup () {
	    thread = std::thread(read_thread, pack);
	}

	void read() {
	    uint32_t mask = (1<<17) - 1;
	    double val1, val2;
	    
	    val1 = double(*pack & mask) / 16;
	    val2 = double(*pack & ~mask) / 16;
	    txt_value = String(val1, 2) + "," + String(val2, 2);
	}
	
	std::atomic<uint32_t> *pack;
	String txt_value;
    private:
	std::thread thread;
};

#endif

Which results into the following error message:

../../../build/target/user/platform-6/libuser.a(sterne.o): In function `thread<void (&)(std::atomic<long unsigned int>*), std::atomic<long unsigned int>*&>':
/usr/local/gcc-arm-embedded-gcc-arm-none-eabi-4_8-2014q2-20140609-linux-tar-bz2/arm-none-eabi/include/c++/4.8.4/thread:135: undefined reference to `std::thread::_M_start_thread(std::shared_ptr<std::thread::_Impl_base>)'
collect2: error: ld returned 1 exit status
make: *** [72ce649f8d9afb1fdb1dbc0e39502e72ea9394d040972ead79696a253ca7.elf] Error 1

Could there be a linking error on the cloud or did I screw up on my end, which is quite possible - since I have very limited multi threading or c++ experience. Thanks for taking a look at it.

There is a wrapper for FreeRTOS threads that would be used something like this

void blink() {
  digitalWrite(D7, HIGH);
  delay(500);
  digitalWrite(D7, LOW);
  delay(500);
}

void hardware_fn() {
  // do setup
  pinMode(D7, OUTPUT);
  // loop forever
  for(;;) {
    blink();
  }
}
void setup() {
  // Thread will start and run hardware_fn
  Thread("hardware", hardware_fn, OS_THREAD_PRIORITY_DEFAULT + 1);
  // Use a slightly higher priority to make sure it interrupts the system and application thread
}
1 Like

Thanks for the fast reply. I will look into this. I have to find the docs for FreeRTOS to find out how to supply a parameter. But this should work.

1 Like