cancel
Showing results for 
Search instead for 
Did you mean: 

printf to serial through a queue

zamek42
Associate II
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
2 REPLIES 2
rchrdlyon1
Associate II
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
Associate II
Posted on November 14, 2016 at 09:25

Hi Richard,

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