This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

RTX Mailbox does not transmit

Trying use RTX mailbox I find it not robust. For some reason some messages can't be received by recipient and mailbox quickly becomes full. To find problem I use slightly modified demo program C:\Keil\ARM\RL\RTX\Examples\Mailbox
Reason for the modification - use LED for output.
This demo program does not work on real STR912FW44. Receiver never takes message from sender. Does somebody use RTX mailbox for the STR9x? Is it some special in the RTX_Config file or STR91x startup file? Followed is my test code that is slightly modified example code. I use V3.20 RTX. Thanks in advance.

/* ********************************************************
 Name: Main.c   Rev. used: V3.20   Chip: STM912FW44
******************************************************** */
#include <rtl.h>
#include <91x_lib.h>

OS_TID idInitTask;
OS_TID idRecTask;

#define MAILBOX_MSG 35  /* command in the message */

typedef struct          /* message object structure */
{
 int imbCommand;
 int iXBeg;
}msgB;

os_mbx_declare(malBx, 20);             /* an RTX mailbox */
_declare_box(poolS, sizeof(msgB), 20); /* mem pool       */

extern void InitializeHardware(void); /* IO pin for LED  */

void InitTask(void) __task;
void RecTask(void) __task;

/* ******************************************************
  RTX Kernel starts this task with os_sys_init
****************************************************** */
void InitTask(void) __task
{
 msgB* msg;
 OS_RESULT res;

 idInitTask = os_tsk_self();           /* get own ID   */
 idRecTask = os_tsk_create(RecTask, 7);/* start task   */

 os_mbx_init(malBx, sizeof(malBx));    /* mailbox init */
 os_dly_wait(5);

 msg = (msgB*)_alloc_box(poolS);       /* alloc mem    */
 if(msg != NULL)
 {
  res = os_mbx_check(malBx);           /* check room   */
  if(res != 0)
  {
   msg->imbCommand = MAILBOX_MSG;      /* set conyent  */
   msg->iXBeg = 3;                     /* set LED off  */
   os_mbx_send(malBx, msg, 0);
  }
 }
 os_dly_wait (100);                    /* some delay   */

 msg = (msgB*)_alloc_box(poolS);       /* second msg   */
 if(msg != NULL)
 {
  res = os_mbx_check(malBx);
  if(res != 0)
  {
   msg->imbCommand = MAILBOX_MSG;
   msg->iXBeg = 2;                     /* set LED ON   */
   os_mbx_send(malBx, msg, 0);
  }
 }
 os_tsk_pass ();           /* Cooperative multitasking */
 os_dly_wait (100);                    /* some delay   */

 os_tsk_delete_self();                 /* delete self  */
}

/*-----------------------------------------------------------
 * RTX Kernel starts this task with os_tsk_create
 *---------------------------------------------------------*/
void RecTask(void) __task
{
 msgB* msg;
 OS_RESULT res;

 for(;;)
 {
  res = os_mbx_wait(malBx, (void**)&msg, 0xFFFF);
  if(res == OS_R_OK)
  {
   switch(msg->imbCommand)
   {
    case MAILBOX_MSG:
     if((msg->iXBeg % 2) != 0)
      GPIO_WriteBit(GPIO6, GPIO_Pin_2, Bit_SET); /* LED OFF */
     else
      GPIO_WriteBit(GPIO6, GPIO_Pin_2, Bit_RESET);/*LED ON */
     break;
   }
   _free_box(poolS, msg); /* free memory */
  }
 }
}

/* **************************************
Initialize and start RTX
************************************** */
int main()
{
 InitializeHardware();  /* init IO   */
 _init_box(poolS,       /* init pool */
      sizeof(poolS), sizeof(msgB));
 os_sys_init(InitTask); /* Init RTX and start task */
 while(1)
  os_tsk_pass();
}

Parents Reply Children
  • Playing with the Mailbox example I discover two issues.
    1. Priority of receiver task should be lover or equal sender task.
    2. Receiver task should not check result of os_mbx_wait function. Followed are two receiver functions.

    /* From Kail's Mailbox example. This works if priority lower or equal sender */
    void rec_task (void) __task
    {
     T_MEAS *rptr;
     for (;;)
     {
      res = os_mbx_wait (MsgBox, (void **)&rptr, 0xffff); /* wait for the message    */
      printf ("\nVoltage: %.2f V\n",rptr->voltage);
      printf ("Current: %.2f A\n",rptr->current);
      printf ("Number of cycles: %d\n",rptr->counter);
      _free_box (mpool, rptr);           /* free memory allocated for message  */
     }
    }
    
    /* Checking result of os_mbx_wait makes this function failed alwais */
    void rec_task (void) __task
    {
     T_MEAS *rptr;
     OS_RESULT res;
    
     for (;;)
     {
      res = os_mbx_wait (MsgBox, (void **)&rptr, 0xffff); /* wait for the message    */
      if(res == OS_R_OK)
      {
        printf ("\nVoltage: %.2f V\n",rptr->voltage);
        printf ("Current: %.2f A\n",rptr->current);
        printf ("Number of cycles: %d\n",rptr->counter);
        _free_box (mpool, rptr);           /* free memory allocated for message  */
      }
     }
    }
    

    Thanks a lot Per for pointing to priority issue. In my original program two sender task send messages to receiver task. One sender task has lower priority than receiver and receiver can't extract this messages and mailbox becomes full. Changing sender priority equal to receiver fixes it. Thanks again.

    Mikhail

  • O-O-Ops, first example should be:

    /* From Kail's Mailbox example. This works if priority lower or equal sender */
    void rec_task (void) __task
    {
     T_MEAS *rptr;
     for (;;)
     {
      os_mbx_wait (MsgBox, (void **)&rptr, 0xffff); /* wait for the message    */
      printf ("\nVoltage: %.2f V\n",rptr->voltage);
      printf ("Current: %.2f A\n",rptr->current);
      printf ("Number of cycles: %d\n",rptr->counter);
      _free_box (mpool, rptr);           /* free memory allocated for message  */
     }
    }
    

  • os_mbx_wait will return 3 different values.

    OS_R_OK if data is waiting in the mailbox
    OS_R_TMO if there is no data before the timeout period
    OS_R_MBX if there was not data in the queue when the wait started, but data comes before the timeout period.

    Therefore the correct statement to determine if you have data is

    if (resulet != OS_R_TMO)
       //have data
    else
       //do not have data
    

    Next you may not issue any mailbox command (save os_mbx_init) until the mailbox is initialized. This means that if you create the rec_task before initializing the mailbox and the receive task has a higher priority than the initTask, you will call os_mbx_wait BEFORE the mailbox is initialized. You may want to initialize the mailbox before calling os_sys_init. This change should allow you to run your tasks at any priority compared to each other.

  • Robert thanks for your explanation. Now it is clear. And it works great in both - example and in my program. I appreciate your help.
    Is it legal initialize mutex and semaphore before calling os_sys_init(...) too?

  • As it stands now it is legal initialize them before the os_sys_init and will likely be that way in the future.