Queuing or communication between thread

benuretech

New member
Hi,
I know that teensy isn't really fully FreeRtos compatible right now but had it's own thread class.

I tend to use quite a bit data queuing in my threading application. Is there something similar with teensy. Something that would allow thread safe communication of data between threads? Everything that I seem to find seems to come with the caveat that it's not thread safe. Which kind of defeat the purpose for me.

And for the question that often come up: "why would you need it" , a bit of a weird question since I don't see much of the need for threading if you can't communicate between thread.

But in my case I have 3 threads.

Thread1: takes the UDP ethernet communication. It takes message in and out, goes through a CRC and escape character. Includes a watch dog. Or send/recieve to other threads.

Thread 2:
UART port (controls a rs485 device). Really slow. Execute commands from ethernet. Some commands can last a couple minute.

Thread 3: ADC stream. Continuously read and filter a 2 signal and send a decimated value to thread 2 every 10ms. The number of sample will just depend on the processor free time.

I would have a hard time to implement this without threads and queuing.

The implementation works fine with rp2040 with free Rtos. I tried to transfer it on teensy hoping a bit better

Anyway, if there's a queuing compatible with the thread safe method,I would love to hear about it.

Thanks
 
Hi,
Try https://github.com/tsandmann/freertos-teensy
Follow installation instructions, and examples would work easily. Then make your own project.

Another very good example is https://github.com/tjaekel/Teesny_4_1
You can find some post here from the author.

The only problem with Freertos on Teensy: if you want a task which should run at each caracter received on a uart, you should periodicaly check its reception. The serial driver is not writen in a way it sends the caracter to a queue during the interrupt, to a waiting task. But depending on your application, it should not be a problem
Angelo
 
Last edited:
Thread1: takes the UDP ethernet communication. It takes message in and out, goes through a CRC and escape character. Includes a watch dog. Or send/recieve to other threads.

Thread 2:
UART port (controls a rs485 device). Really slow. Execute commands from ethernet. Some commands can last a couple minute.

Thread 3: ADC stream. Continuously read and filter a 2 signal and send a decimated value to thread 2 every 10ms. The number of sample will just depend on the processor free time.

I would have a hard time to implement this without threads and queuing.

Instead of TeensyThreads or FreeRTOS, I use a simple cooperative "OS" that I built myself, with mailboxes and queues for inter-task and ISR-to-task communication and this works very well for me. The underlying C queue is shown below, with each queue element being of type *void. If you look at library FreqMeasureMulti, you can see an example of a simple C++ queue with more complex element. The ISR writes to the queue and the library includes functions to read from the queue.

Code:
/*******************************************************************************
* ISQUEUE.H    Interrupt-safe queue (ring bffer)
*
* Copyright (c) Fenway Systems LLC, 2021. Contact: joep@fenway.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice, development funding notice, and this permission
* notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*******************************************************************************/
#if (!defined(__ISQUEUE_H_))
#define __ISQUEUE_H_

typedef struct {
  void** buf;        // ptr to start of buffer
  int    size;        // # of elements
  int    head;        // index of next (empty) element to write
  int    tail;        // index of next (full) element to read
} ISQ;

void q_init ( ISQ* q, void** buf, int size );
int  q_get  ( ISQ* q, void** data );
int  q_put  ( ISQ* q, void*  data );
int  q_count( ISQ* q );
int  q_empty( ISQ* q );

#endif

Code:
/*******************************************************************************
* ISQUEUE.C    Interrupt-safe queue (ring buffer)
*
* Copyright (c) Fenway Systems LLC, 2021. Contact: joep@fenway.com
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice, development funding notice, and this permission
* notice shall be included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*******************************************************************************/
#include "isqueue.h"

/*******************************************************************************
* q_init()    Init queue with provided buffer and size
*******************************************************************************/
void q_init( ISQ* q, void** buf, int size )
{
  q->buf  = buf;
  q->size = size;
  q->head = 0;
  q->tail = 0;
}

/*******************************************************************************
* q_get()    Get data from head of queue (return 0 if empty, else 1)
*******************************************************************************/
int q_get( ISQ* q, void** data )
{
  if (q->tail == q->head)        // if q is empty
    return(0);                //   return 0 = fail
  else {                // else
    *data = q->buf[q->head];        //   get data value
    q->head = q->head + 1;        //   update head
    if (q->head >= q->size)        //   if beyond end of buffer
      q->head = 0;            //     wrap to 0
    return (1);                //   return 1 = success
  }
}

/*******************************************************************************
* q_put()    Put data to tail of queue (return 0 if full, else 1)
*******************************************************************************/
int q_put( ISQ* q, void* data )
{
  int next = q->tail + 1;        // value of tail AFTER write
  if (next >= q->size)            // if beyond end of buffer
    next = 0;                //   wrap to 0
  if (next == q->head)            // if buffer is full
    return( 0 );            //   return 0 = fail
  else {                // else
    q->buf[q->tail] = data;        //   write data to buffer
    q->tail = next;            //   update tail
    return( 1 );            //   return 1 = success
  }
}

/*******************************************************************************
* q_count()    Return number of items in queue
*******************************************************************************/
int q_count( ISQ* q )
{
  int count = q->tail - q->head;
  return( (count >= 0) ? (count) : (q->size + count) );
}

/*******************************************************************************
* q_empty()    Return 1 if empty, else 0
*******************************************************************************/
int q_empty( ISQ* q )
{
  return(q->head == q->tail ? 1 : 0);
}
 
Back
Top