Mailbox message

Discussions and support about ChibiOS/RT, the free embedded RTOS.
Post Reply
Captain
Posts: 12
Joined: Sat Dec 19, 2015 3:21 pm

Mailbox message

Post by Captain »

Hello!

What seems odd to me about the chMBPost function is that it accepts an outgoing message parameter as a msg_t, which comes to be a simple int32_t. Any way to pass an array or struct between threads, using a mailbox?
steved
Posts: 834
Joined: Fri Nov 09, 2012 2:22 pm
Has thanked: 12 times
Been thanked: 138 times

Re: Mailbox message

Post by steved »

You can also use it as a pointer, and pass an array or structure by reference (I think there are other threads covering this)
Obviously its then up to you to manage the referenced memory block as required
jscott
Posts: 129
Joined: Tue Jul 03, 2012 3:50 pm

Re: Mailbox message

Post by jscott »

You might want to look at post:

http://forum.chibios.org/phpbb/viewtopic.php?f=2&t=2980

It shows a small function that allows creating a buffer pool, allocating buffers pointers that you can pass in mailboxes, then freeing the buffer back to the pool.

-John
Captain
Posts: 12
Joined: Sat Dec 19, 2015 3:21 pm

Re: Mailbox message

Post by Captain »

Thanks, now it's clear.
Not to create another topic, I'll ask here. The code:

Code: Select all

#include "ch.h"
#include "hal.h"
#include "test.h"
#include "usbcfg.h"
#include <string.h>

SerialUSBDriver SDU1;
static void adcCapture_cb(ADCDriver *adcp, adcsample_t *buffer, size_t n);

static uint32_t MBBuf1[4], MBBuf2[4], MBBuf3[4];
static adcsample_t ADCBuf[3];

MAILBOX_DECL(TCTempMB, MBBuf1, sizeof(MBBuf1));

const ADCConversionGroup adg = { true,                    // circular
                                 3,                       // num_channels
                                 adcCapture_cb,           // end_cb
                                 NULL,                    // error_cb
                                 ADC_CFGR1_RES_10BIT,     // cfgr1
                                 0,                       // tr
                                 ADC_SMPR_SMP_239P5,      // smpr
                                                          // chselr
                                 (1U << 0U) |             //  ADC_IN0 - TEMP_SNS
                                 (1U << 1U) |             //  ADC_IN1 - VBAT
                                 (1U << 13U)              //  ADC_IN13 - HEATER_CUR
                               };

static void adcCapture_cb(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
  (void) n;
  (void) adcp;

  chSysLockFromISR();

  chMBPostI(&TCTempMB, 0xDEADFACE);   // Placeholder

  chSysUnlockFromISR();
}

THD_WORKING_AREA(waControlLoop, 128);
THD_FUNCTION(thdControlLoop, arg) {
  (void) arg;
  uint32_t v;

  BaseAsynchronousChannel *stream = (BaseAsynchronousChannel *) arg;

  adcStartConversion(&ADCD1, &adg, ADCBuf, 1);

  while( true ) {
    chMBFetch(&TCTempMB, (msg_t *) &v, TIME_INFINITE);
    chnWrite(stream, (uint8_t *) &v, sizeof(v));
  }
}

int main(void) {

  halInit();
  chSysInit();

  usbDisconnectBus(serusbcfg.usbp);
  chThdSleepMilliseconds(1000);
  usbStart(serusbcfg.usbp, &usbcfg);
  usbConnectBus(serusbcfg.usbp);

  sduObjectInit(&SDU1);
  sduStart(&SDU1, &serusbcfg);

  adcStart(&ADCD1, NULL);

  chThdSleepMilliseconds(500);
  chThdCreateStatic(waControlLoop, sizeof(waControlLoop), NORMALPRIO, thdControlLoop, &SDU1);

  while (true) {

    chThdSleepMilliseconds(500);
  }
}

The adcCapture_cb callback never runs. When I run blocking adcConvert, it seems to work fine. What could be wrong?
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Mailbox message

Post by Giovanni »

Hi,

Try compiling using -O0, then enable debug options in chconf.h (assertions, checks, state checker) and place a breakpoint into the callback.

Giovanni
Captain
Posts: 12
Joined: Sat Dec 19, 2015 3:21 pm

Re: Mailbox message

Post by Captain »

Ok, here is what I have found.
The callback fires perfectly, except I had to enable STM32 CONTinuous ADC mode so it would restart each round:
ADC_CFGR1_RES_10BIT | (1U << 13U), // cfgr1 CONT=1

Now the callback code and the single thread running together:

Code: Select all

static void adcCapture_cb(ADCDriver *adcp, adcsample_t *buffer, size_t n) {
   (void) n;
   (void) adcp;

   chSysLockFromISR();

   if(chMBGetFreeCountI(&TCTempMB) != 0) {
      chMBPostI(&TCTempMB, buffer[0]);
   }

   chSysUnlockFromISR();
}

THD_WORKING_AREA(waControlLoop, 128);
THD_FUNCTION(thdControlLoop, arg) {
   (void) arg;
   uint32_t v1;

   BaseAsynchronousChannel *stream = (BaseAsynchronousChannel *) arg;

   adcStartConversion(&ADCD1, &adg, ADCBuf, 1);

   while ( true ) {
      chMBFetch(&TCTempMB, (msg_t *) &v1, TIME_INFINITE);
      chnWrite(stream, (uint8_t * ) &v1, sizeof(v1));
      chThdSleepMilliseconds(500);
   }

When it reaches the chThdSleepMilliseconds(500);, the unhandled exception occurs. After stepping the code, I've found that it happens on the chSysSwitch(currp, otp) invocation from within chschd.c. Any idea?

Also, if I remove chThdSleepMilliseconds(500), no exception happens, but when connecting through terminal it hangs deadly. Might that be because of ADC interrupt firing too fast and blocking USB request callbacks?
User avatar
Giovanni
Site Admin
Posts: 14891
Joined: Wed May 27, 2009 8:48 am
Has thanked: 1202 times
Been thanked: 996 times

Re: Mailbox message

Post by Giovanni »

It is possible, the ADC is a very fast peripheral so continuous mode must be used carefully. You may increase sample time or use HW triggering. You may also call adcConvert() directly from the thread, depending on what you are trying to do.

About chMBPostI(), you don't need to check if there is space beforehand, in that case the function simply fails.

Also check if you are hitting a stack overflow issue.

Giovanni
Captain
Posts: 12
Joined: Sat Dec 19, 2015 3:21 pm

Re: Mailbox message

Post by Captain »

Thank you, Giovanni. It finally explains why usb works fine when I remove code within the callback.
Post Reply