Skip to main content
zamek42
Associate II
October 30, 2016
Question

printf to serial through a queue

  • October 30, 2016
  • 2 replies
  • 1095 views
Posted on October 30, 2016 at 10:11

Hi All,

I would like to use a queue to send printf outputs to a serial port. When I try to send something into the queue, its freezes after 3rd character. Here is the queue init code:

static struct {
osMessageQId receive_queue;
osMessageQId transmit_queue;
}console;
void console_init(void) {
if (!console_stream)
return;
osMessageQDef(transmit_queue,CONSOLE_BUFFER_SIZE, sizeof(uint8_t));
console.transmit_queue = osMessageCreate(osMessageQ(transmit_queue), NULL);
osMessageQDef(receive_queue, CONSOLE_BUFFER_SIZE, sizeof(uint8_t));
console.receive_queue = osMessageCreate(osMessageQ(receive_queue), NULL);
}

here is the putchar code:

PUTCHAR_PROTOTYPE
{
osMessagePut(console.transmit_queue, ch, 100);
return ch;
}

and here is the serial task code:

void console_task_func(void) {
if (!console_stream)
return;
osEvent ev;
for(;;) {
ev = osMessageGet(console.transmit_queue, 100);
if (ev.status==osEventMessage)
HAL_UART_Transmit(console_stream, (uint8_t *)&ev.value, (uint16_t)1, 10U);
}
}

I there any specialities if I want to use it from printf? thx Zamek #queue #printf
    This topic has been closed for replies.

    2 replies

    rchrdlyon1
    Associate II
    November 3, 2016
    Posted on November 03, 2016 at 13:34

    A couple of things:

    You can capture the printf output by implementing ''int _write(int fd, char *ptr, int len)''.

    Use a mail queue instead of a message queue, it's more efficient.

    Some example code I use with the STM32F407. printf output is captured an transferred to a diagnostic task using a mail queue. The task transmits the output to a serial port. Not much code, but effective. I'm sure you can improve it.

    --------------------------------------------------------------------------------

    /* maximum permissible length of the mail data */

    #define DIAG_MAIL_SIZE 255

    /* definition of diagnostic serial mail type */

    struct DIAG_MAIL

    {

        /* an array for holding the data (normally a string) */

        char data[DIAG_MAIL_SIZE];

        /* the length of the data (normally the length a string) */

        uint8_t length;

    };

    --------------------------------------------------------------------------------

    void MX_FREERTOS_Init(void) {

      .....

     

      /* USER CODE BEGIN RTOS_QUEUES */

      /* DiagSend mail queue */

      osMailQDef(DiagSend, 8, struct DIAG_MAIL);

      DiagSendHandle = osMailCreate(osMailQ(DiagSend), NULL);

      /* USER CODE END RTOS_QUEUES */

     

      ......

     

    }

    ---------------------------------------------------------------------------------

    /* global function to redirect printf */

    int _write(int fd, char *ptr, int len)

    {

        int result = 0;

        if ((fd == STDOUT_FILENO) && (ptr != NULL) && (len > 0))

        {

            struct DIAG_MAIL* ptr_mail = osMailAlloc(DiagSendHandle, 0);

            if (ptr_mail != NULL)

            {

                /* if necessary truncate the data length */

                if (len > DIAG_MAIL_SIZE)

                {

                    len = DIAG_MAIL_SIZE;

                };

                /* copy data into the mail message */

                arm_copy_q7((q7_t*) ptr, (q7_t*) ptr_mail->data, len);

                ptr_mail->length = len;

                /* put the mail into the queue */

                osMailPut(DiagSendHandle, ptr_mail);

                /* return the actual number of bytes placed in mail queue */

                result = len;

            };

        };

        return result;

    }

    ------------------------------------------------------------------------------

    /* diagnostic serial task function */

    void DiagSerTask(void const* argument)

    {

        /* task loop */

        while (1)

        {

            /* wait for an incoming mail */

            osEvent evt = osMailGet(DiagSendHandle, osWaitForever);

            if (evt.status == osEventMail)

            {

                /* save pointer to mail */

                struct DIAG_MAIL* ptr_mail = evt.value.p;

                /* transmit over serial port */

                HAL_UART_Transmit_IT(&huart2, (uint8_t*) ptr_mail->data,

                        ptr_mail->length);

                /* wait for notification of transmission completion */

                ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

                /* free mail */

                osMailFree(DiagSendHandle, ptr_mail);

            };

        };

    }

    /* serial transmit callback */

    void HAL_UART_TxCpltCallback(UART_HandleTypeDef *ptr_huart)

    {

        if (ptr_huart->Instance == USART2)

        {

            BaseType_t xHigherPriorityTaskWoken = pdFALSE;

            /* notify task that the serial transmission is completed */

            vTaskNotifyGiveFromISR(DiagSerHandle, &xHigherPriorityTaskWoken);

            /* ensure return to highest priority unblocked */

            portYIELD_FROM_ISR(xHigherPriorityTaskWoken);

        };

    }

    ---------------------------------------------------------------------------

    stmcube was used to setup USART2. use google to find out more about the printf/_write functions, etc ...

    zamek42
    zamek42Author
    Associate II
    November 14, 2016
    Posted on November 14, 2016 at 09:25

    Hi Richard,

    Thx a lot, it seems to be good for me:)