Send any information to task.

Discussions and support about ChibiOS/RT, the free embedded RTOS.
vjoszef
Posts: 3
Joined: Thu Dec 28, 2017 10:33 am

Send any information to task.

Postby vjoszef » Thu Dec 28, 2017 11:05 am

Hi all!

I'm beginner in ChibiOs. My question is how to send information(structure) to a task?
I need send msg data from ledoff to Thread3 if data arrived from serial.

Code: Select all

#include "ch.h"
#include "ch.hpp"
#include "hal.h"
#include "string.h"

using namespace chibios_rt;
static virtual_timer_t vt2;
uint16_t cb[50];
uint8_t cb_p=0;


struct messageData
{
  int timeStamp;
  char cmd;
  uint8_t tmr;
};


static THD_WORKING_AREA(waThread2, 128);
static THD_WORKING_AREA(waThread3, 128);

// This function will become the code for thread 2
static void Thread3(void *arg)
{
    (void)arg;
    messageData *msg;
    thread_t *tp;
    chRegSetThreadName("Yellow Blinker");
    int i=0;



    while (TRUE)
    {
      // >>>>>>>>>> Need the msg pointer for processing <<<<<<<<<<<<<<
      tp=chMsgWait();
      msg=(messageData*)chMsgGet(tp);

      if (msg->cmd=='B')
      {
        for (i=0;i<msg->tmr;i++)
        {
          palClearPad(GPIOD, GPIOD_LED6);
          chThdSleepMilliseconds( 250 );      // delay 250mS
          palSetPad(GPIOD, GPIOD_LED6);
          chThdSleepMilliseconds( 50 );      // delay 50mS

        }
        chMsgRelease(tp,(msg_t)&msg);
      }
      else
      if (msg->cmd=='V')
      {
          palClearPad(GPIOD, GPIOD_LED6);
          chThdSleepSeconds(msg->tmr);      // delay tmr*s
          palSetPad(GPIOD, GPIOD_LED6);


           chMsgRelease(tp,(msg_t)&msg);
      }
      else
        chMsgRelease(tp,(msg_t)&msg);

    }
   // return 0;
}

// This function will become the code for thread 2
static void Thread2(void *arg)
{
    (void)arg;
    chRegSetThreadName("Green Blinker");
    while (TRUE)
    {
        palClearPad(GPIOD, GPIOD_LED4);
        chThdSleepMilliseconds( 2000 );      // delay 2000mS
        palSetPad(GPIOD, GPIOD_LED4);
        chThdSleepMilliseconds( 50 );      // delay 50mS
    }
   // return 0;
}





static void ledoff(void *p) {

  (void)p;

  messageData msg;

  if (cb_p>0)
  {
    if (cb[0]==(uint16_t)'B')
    {
      msg.cmd = (uint16_t)'B';
      msg.tmr=200;
      msg.timeStamp=chVTGetSystemTime();
      chMsgSend(?????,(msg_t)msg);
     // >>>>>>>>>>> Need to send msg pointer to send to Thread3 <<<<<<<<<<<
    }

    if (cb[0]==(uint16_t)'V')
    {
      msg.cmd = (uint16_t)'V';
      msg.tmr=100;
      msg.timeStamp=chVTGetSystemTime();

      chMsgSend(?????,(msg_t)msg);
      // >>>>>>>>>>> Need to send msg pointer to send to Thread3 <<<<<<<<<<<
    }
    uartStartSend(&UARTD2, cb_p-1, cb);
    cb_p=0;
  }
  palClearPad(GPIOD, GPIOD_LED5);
}
/*
 * This callback is invoked when a character is received but the application
 * was not ready to receive it, the character is passed as parameter.
 */
static void rxchar(UARTDriver *uartp, uint16_t c) {




  (void)uartp;
  (void)c;
  /* Flashing the LED each time a character is received.*/
  if (cb_p<50)
  {
    cb[cb_p]=c;
    cb_p++;
  }
  palSetPad(GPIOD, GPIOD_LED5);
  chSysLockFromISR();

  // reset timer if more data arrived
  chVTResetI(&vt2);

  // Set timer to 200 tick and call 'ledoff' on timeout
  chVTSetI(&vt2, MS2ST(200), ledoff, NULL);
  chSysUnlockFromISR();
}

/*
 * This callback is invoked when a receive buffer has been completely written.
 */
static void rxend(UARTDriver *uartp) {

  (void)uartp;
}



/*
 * UART driver configuration structure.
 */

static UARTConfig uartcfg = {
           NULL,
            NULL,
            rxend,
            rxchar,
            NULL,
            115200,
            0,
            USART_CR2_LINEN,
            0
};

/*
 * Application entry point.
 */
int main(void) {
 const char *st;


  halInit();
  System::init();

  uartStart(&UARTD2, &uartcfg);
   palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7));
   palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7));
  /*
   * Serves timer events.
   */


  thread_t *ctp=chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO, Thread2, NULL);
  chThdCreateStatic(waThread3, sizeof(waThread3), NORMALPRIO, Thread3, NULL);

  st=chRegGetThreadNameX(ctp);
  uartStartSend(&UARTD2, 16, st);

  while (true) {
    palClearPad(GPIOD, GPIOD_LED3);
    chThdSleepMilliseconds( 500 );      // delay 500mS
    palSetPad(GPIOD, GPIOD_LED3);

    chThdSleepMilliseconds( 500 );      // delay 500mS

  }

  return 0;
}

User avatar
Giovanni
Site Admin
Posts: 14455
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: Send any information to task.

Postby Giovanni » Thu Dec 28, 2017 12:06 pm

Hi,

If the thread is always waiting for a message then you can use synchronous messages (like in your example), if you need to do asynchronous processing then there are mailboxes.

Note that if you wait for messages then those chThdSleep() are not necessary, it is chMsgWait() that stops the thread.

There are examples here: http://www.chibios.org/dokuwiki/doku.ph ... ge_passing

Giovanni

vjoszef
Posts: 3
Joined: Thu Dec 28, 2017 10:33 am

Re: Send any information to task.

Postby vjoszef » Thu Dec 28, 2017 1:59 pm

Thank You!

I Don't need wait for response. I thinking in mailboxes, but the messages is only msg_t type (int32_t) not a pointer. Like below:

Code: Select all

msg_t chMBPost   (   Mailbox *    mbp,
msg_t    msg,
systime_t    time
)



So I can't send msg struct:

Code: Select all

struct messageData
{
  int timeStamp;
  char cmd;
  uint8_t tmr;
};
messageData msg;

  chMBPost(&mbox,(msg_t)&msg,TIME_INFINITE);

User avatar
Giovanni
Site Admin
Posts: 14455
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: Send any information to task.

Postby Giovanni » Thu Dec 28, 2017 2:08 pm

Hi,

The type msg_t is guaranteed to be cast-able to a pointer, it is a common use case.

Giovanni

vjoszef
Posts: 3
Joined: Thu Dec 28, 2017 10:33 am

Re: Send any information to task.

Postby vjoszef » Thu Dec 28, 2017 3:58 pm

Hi, I'm modify the code for mailbox and mempool this work fine!

My next goal the dynamic tasks.

-Arrived a command block from serial.
-Load the task to pool and pass the arrived command block and run it.
-After task reload from pool and freeing space for other task.

I cannot find an example for ChibiOS 17.6.0


Code: Select all

#include "ch.h"
#include "ch.hpp"
#include "hal.h"
#include "string.h"
#include <stdlib.h>     /* atoi */


using namespace chibios_rt;
static virtual_timer_t vt2;
uint16_t cb[50];
uint8_t cb_p=0;


#define MB_SIZE 6
//static mailbox_t mbox;//[MB_SIZE];

typedef struct
{
  int timeStamp;
  char cmd;
  uint8_t tmr;
} messageData;

static char buffer[sizeof(messageData)*MB_SIZE];


memory_pool_t *pool;

//static MEMORYPOOL_DECL(pool, sizeof(messageData)*MB_SIZE, NULL);
static MAILBOX_DECL(mbox, buffer, sizeof(buffer));



static THD_WORKING_AREA(waThread2, 128);
static THD_WORKING_AREA(waThread3, 128);

// This function will become the code for thread 2

static THD_FUNCTION(Thread3, arg)
{

    (void)arg;


    chRegSetThreadName("Yellow Blinker");
    int i=0;
   // msg_t msg1;
    messageData *msg2;



    while (TRUE)
    {

       chMBFetch(&mbox, (msg_t *)&msg2, TIME_INFINITE);


        if (msg2->cmd=='B')
        {
       for (i=0;i<msg2->tmr;i++)
          {
            palSetPad(GPIOD, GPIOD_LED6);
            chThdSleepMilliseconds( 20 );      // delay 250mS
            palClearPad(GPIOD, GPIOD_LED6);
            chThdSleepMilliseconds( 200 );      // delay 50mS

          }
        }
        else
        if (msg2->cmd=='V')
        {
            palSetPad(GPIOD, GPIOD_LED6);
            chThdSleepSeconds(msg2->tmr);      // delay tmr*s
            palClearPad(GPIOD, GPIOD_LED6);



        }

        chPoolFree(pool, (void *)&msg2);

    }
   // return 0;
}

// This function will become the code for thread 2
static void Thread2(void *arg)
{
    (void)arg;
    chRegSetThreadName("Green Blinker");
    while (TRUE)
    {
        palClearPad(GPIOD, GPIOD_LED4);
        chThdSleepMilliseconds( 2000 );      // delay 2000mS
        palSetPad(GPIOD, GPIOD_LED4);
        chThdSleepMilliseconds( 50 );      // delay 50mS
    }
   // return 0;
}





static void ledoff(void *p) {

  (void)p;
  char ct[8];

  if (cb_p<4 )
  {
    uartStartSend(&UARTD2, 4, "ERROR");
    //chprintf((BaseSequentialStream*)&UARTD2,"Error\r\n");
  }
  else
  if (cb_p>0)
  {
       ct[0]=cb[1];
       ct[1]=cb[2];
       ct[2]=cb[3];
       ct[3]=13;

    if (cb[0]==(uint16_t)'B')
    {

      //grab a memory pool item
      messageData *msg = (messageData *)chPoolAlloc(pool);
      if (msg != NULL)
      {
        msg->cmd = (uint16_t)'B';
        msg->tmr=atoi(ct);
        msg->timeStamp=chVTGetSystemTime();
        chMBPost(&mbox,(msg_t)msg,TIME_INFINITE);
      }
      // >>>>>>>>>>> Need to send msg pointer to send to Thread3 <<<<<<<<<<<
    }

    if (cb[0]==(uint16_t)'V')
    {
      messageData *msg = (messageData *)chPoolAlloc(pool);
      if (msg != NULL)
      {
        msg->cmd = (uint16_t)'V';
        msg->tmr=atoi(ct);
        msg->timeStamp=chVTGetSystemTime();
        chMBPost(&mbox,(msg_t)msg,TIME_INFINITE);
      }

      // >>>>>>>>>>> Need to send msg pointer to send to Thread3 <<<<<<<<<<<
    }
    uartStartSend(&UARTD2, cb_p-1, cb);

  }
  cb_p=0;
  palClearPad(GPIOD, GPIOD_LED5);
}
/*
 * This callback is invoked when a character is received but the application
 * was not ready to receive it, the character is passed as parameter.
 */
static void rxchar(UARTDriver *uartp, uint16_t c) {




  (void)uartp;
  (void)c;
  /* Flashing the LED each time a character is received.*/
  if (cb_p<50)
  {
    cb[cb_p]=c;
    cb_p++;
  }
  palSetPad(GPIOD, GPIOD_LED5);
  chSysLockFromISR();

  // reset timer if more data arrived
  chVTResetI(&vt2);

  // Set timer to 200 tick and call 'ledoff' on timeout
  chVTSetI(&vt2, MS2ST(200), ledoff, NULL);
  chSysUnlockFromISR();
}

/*
 * This callback is invoked when a receive buffer has been completely written.
 */
static void rxend(UARTDriver *uartp) {

  (void)uartp;
}



/*
 * UART driver configuration structure.
 */

static UARTConfig uartcfg = {
           NULL,
            NULL,
            rxend,
            rxchar,
            NULL,
            115200,
            0,
            USART_CR2_LINEN,
            0
};

/*
 * Application entry point.
 */
int main(void) {
 const char *st;
 //mailbox_t mbox;

  halInit();
  System::init();
  chPoolObjectInit(pool,sizeof(messageData)*4,NULL);
  //chMBObjectInit(&mbox, (msg_t*)messageData, MB_SIZE);
  uartStart(&UARTD2, &uartcfg);
   palSetPadMode(GPIOA, 2, PAL_MODE_ALTERNATE(7));
   palSetPadMode(GPIOA, 3, PAL_MODE_ALTERNATE(7));
  /*
   * Serves timer events.
   */


  thread_t *ctp=chThdCreateStatic(waThread2, sizeof(waThread2), NORMALPRIO, Thread2, (void*)&mbox);
  chThdCreateStatic(waThread3, sizeof(waThread3), NORMALPRIO, Thread3, (void*)&mbox);

  st=chRegGetThreadNameX(ctp);
  uartStartSend(&UARTD2, 16, st);

  while (true) {
    palClearPad(GPIOD, GPIOD_LED3);
    chThdSleepMilliseconds( 500 );      // delay 500mS
    palSetPad(GPIOD, GPIOD_LED3);

    chThdSleepMilliseconds( 500 );      // delay 500mS

  }

  return 0;
}

User avatar
Giovanni
Site Admin
Posts: 14455
Joined: Wed May 27, 2009 8:48 am
Location: Salerno, Italy
Has thanked: 1076 times
Been thanked: 922 times
Contact:

Re: Send any information to task.

Postby Giovanni » Thu Dec 28, 2017 5:34 pm

Hi,

Why create a task each time, the memory is allocated already, you can just let them wait for requests via mailboxes, no?

Anyway, it is possible to create tasks from pools, that would be your use case, waiting the task using chThdWait() returns the task to the source pool on exit.

The examples you want are in the test suite, look at the test sequence regarding dynamic threads.

Giovanni


Return to “ChibiOS/RT”

Who is online

Users browsing this forum: No registered users and 7 guests