Problem with lwip mailbox or FreeRTOS Queue

jesperv wrote on Monday, June 15, 2009:

I’m implementing lwip version 1.3.0 on the newly added FreeRTOS port for AVR32 AP7000 but i’m having a problem with a mailbox in lwip or a queue in FreeRTOS.

I have a printf in netcom accept just after the creation of the newconn pointer and after the sys_arch_mbox_fetch and they prints: "newconn 0x2af6" and "mbox fetch: 0x10013540 conn: 0x2af6 recmbox: 0xf01f0046"

In accept_function i have a printf just before the data is added to the mailbox and looks like this: "mailbox: 0x10013540 conn 0x10002600 recvmbox: 0x100136b0"

Why isn’t the data properly sent through the mailbox or queue?

Here’s the code from lwip:

/**
* Accept a new connection on a TCP listening netconn.
*
* @param conn the TCP listen netconn
* @return the newly accepted netconn or NULL on timeout
*/
struct netconn *
netconn_accept(struct netconn *conn)
{
  struct netconn *newconn;

  printf("newconn %p\n", newconn);

  LWIP_ERROR("netconn_accept: invalid conn",       (conn != NULL),                      return NULL;);
  LWIP_ERROR("netconn_accept: invalid acceptmbox", (conn->acceptmbox != SYS_MBOX_NULL), return NULL;);

#if LWIP_SO_RCVTIMEO
  if (sys_arch_mbox_fetch(conn->acceptmbox, (void *)&newconn, conn->recv_timeout) == SYS_ARCH_TIMEOUT) {
    newconn = NULL;
  } else
#else

  sys_arch_mbox_fetch(conn->acceptmbox, (void *)&newconn, 0);
  printf("mbox fetch: %p\ conn: %p recmbox: %p\n",conn->acceptmbox, newconn, newconn->recvmbox);
#endif /* LWIP_SO_RCVTIMEO*/
  {
    /* Register event with callback */
    API_EVENT(conn, NETCONN_EVT_RCVMINUS, 0);

#if TCP_LISTEN_BACKLOG
    if (newconn != NULL) {
      /* Let the stack know that we have accepted the connection. */
      struct api_msg msg;
      msg.function = do_recv;
      msg.msg.conn = conn;
      TCPIP_APIMSG(&msg);
    }
#endif /* TCP_LISTEN_BACKLOG */
  }
  return newconn;
}

/**
* Accept callback function for TCP netconns.
* Allocates a new netconn and posts that to conn->acceptmbox.
*
* @see tcp.h (struct tcp_pcb_listen.accept) for parameters and return value
*/
static err_t
accept_function(void *arg, struct tcp_pcb *newpcb, err_t err)
{
  struct netconn *newconn;
  struct netconn *conn;

#if API_MSG_DEBUG
#if TCP_DEBUG
  tcp_debug_print_state(newpcb->state);
#endif /* TCP_DEBUG */
#endif /* API_MSG_DEBUG */
  conn = (struct netconn *)arg;

  LWIP_ERROR("accept_function: invalid conn->acceptmbox",
             conn->acceptmbox != SYS_MBOX_NULL, return ERR_VAL;);

  /* We have to set the callback here even though
   * the new socket is unknown. conn->socket is marked as -1. */
  newconn = netconn_alloc(conn->type, conn->callback);
  if (newconn == NULL) {
    return ERR_MEM;
  }
  newconn->pcb.tcp = newpcb;
  setup_tcp(newconn);
  newconn->err = err;
  /* Register event with callback */
  API_EVENT(conn, NETCONN_EVT_RCVPLUS, 0);

  printf("mailbox: %p conn %p recvmbox: %p\n", conn->acceptmbox, newconn, newconn->recvmbox);
  if (sys_mbox_trypost(conn->acceptmbox, newconn) != ERR_OK) {
    /* When returning != ERR_OK, the connection is aborted in tcp_process(),
       so do nothing here! */
    newconn->pcb.tcp = NULL;
    netconn_free(newconn);
    return ERR_MEM;
  }
  return ERR_OK;
}

/*
  Blocks the thread until a message arrives in the mailbox, but does
  not block the thread longer than "timeout" milliseconds (similar to
  the sys_arch_sem_wait() function). The "msg" argument is a result
  parameter that is set by the function (i.e., by doing "*msg =
  ptr"). The "msg" parameter maybe NULL to indicate that the message
  should be dropped.

  The return values are the same as for the sys_arch_sem_wait() function:
  Number of milliseconds spent waiting or SYS_ARCH_TIMEOUT if there was a
  timeout.

  Note that a function with a similar name, sys_mbox_fetch(), is
  implemented by lwIP.
*/
u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **msg, u32_t timeout)
{
void *dummyptr;
portTickType StartTime, EndTime, Elapsed;

    StartTime = xTaskGetTickCount();

    if( msg == NULL )
    {
        msg = &dummyptr;
    }
   
    if(    timeout != 0 )
    {
        if(pdTRUE == xQueueReceive( mbox, &(*msg), timeout ) )
        {       
                       
            EndTime = xTaskGetTickCount();
            Elapsed = EndTime - StartTime;
            if( Elapsed == 0 )
            {
                Elapsed = 1;
            }
            return ( Elapsed );
        }
        else // timed out blocking for message
        {
            *msg = NULL;
            return SYS_ARCH_TIMEOUT;
        }
    }
    else // block forever for a message.
    {
        while( pdTRUE != xQueueReceive( mbox, &(*msg), portMAX_DELAY ) ) // time is arbitrary
        {
            ;
        }
        EndTime = xTaskGetTickCount();
        Elapsed = EndTime - StartTime;
        if( Elapsed == 0 )
        {
            Elapsed = 1;
        }
        return ( Elapsed ); // return time blocked TBD test   
    }
}

/*-----------------------------------------------------------------------------------*/
//   Try immediately posting the "msg" to the mailbox.
err_t
sys_mbox_trypost(sys_mbox_t mbox, void *data)
{      
    if ( xQueueSend( mbox, &data, ( portTickType ) 1 ) == pdPASS )
    {
        return ERR_OK;
    }
    else
    {
        return ERR_MEM;
    }
}

jesperv wrote on Monday, June 15, 2009:

Nevermind. I found the problem.
When a new mailbox is created i had changed the size from sizeof( void * )  to a dynamic size. This is not a good idea when queues in FreeRTOS use void pointers.