0

I'm trying to read from a uart port telemetry from a pixhawk 4 device, and forward it to another. I can read it successfully however I am skipping some messages. I've tried using a buffer with size 1 however I believe that was one of my problems.

Thank you for your help

Here's what I have:

My buffers and how I start DMA to get the callback...


/* USER CODE BEGIN 0 */

#define MAX_BUFFER_APS_SIZE 128

uint8_t APS_Buffer[MAX_BUFFER_APS_SIZE];
mavlink_message_t current_message;
mavlink_status_t current_status;
/* USER CODE END 0 */

/* USER CODE BEGIN 2 */

  //start DMA buffers
  HAL_UARTEx_ReceiveToIdle_DMA(&huart4, APS_Buffer, MAX_BUFFER_APS_SIZE);
/* USER CODE END 2 */

while loop in main is empty for now. I've commented all so it is just a "continue"

my callback:


/* USER CODE BEGIN 4 */

void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{
        if (huart->Instance == UART4) //aps
        {
            for (int i = 0; i < Size; i++)
            {
                uint8_t c = APS_Buffer[i];

                if (mavlink_parse_char(MAVLINK_COMM_1, c, &current_message, &current_status)) {

                    ParseMavlinkMessage(current_message);


                    last_msg_received_seq_number = current_message.seq;

                    // Clear the status for the next iteration
                    current_status.packet_rx_drop_count = 0;
                }

            }
        }
}

void ParseMavlinkMessage(mavlink_message_t message)
{

    //sending the message to uart 3
    uint8_t data[MAVLINK_MAX_PACKET_LEN];
    uint16_t len = mavlink_msg_to_send_buffer(data, &message);

    HAL_UART_Transmit(&huart3, data, len, 1000);

    switch(message.msgid)
    {
        case MAVLINK_MSG_ID_OPERATIONAL_STATUS:
        {
            mavlink_msg_operational_status_decode(&message, &operational_status);
            break;
        }
        ... other similar cases...
    }


    //code used to debug that messages are being skipped...

    char msg_to_send[100];
    if(current_message.seq != (last_msg_received_seq_number +1 ) % 256)
    {
        sprintf(msg_to_send, "Autopilot Parsing Thread - Message skipped -> %d | previous message was -> %d\n\r", current_message.seq, last_msg_received_seq_number);
        HAL_UART_Transmit(&huart3, (uint8_t *)msg_to_send, strlen(msg_to_send), 1);
    }

...some other logic...

}

1 Answers1

2

Your interrupt callback function should be as short as possible and definitely not parse and send the data. It should only manage the buffer and return. The parsing and sending should be done by the main program or another task if you use RTOS. It is a general rule - interrupt handlers have to be as short and fast as possible. Do not use them to implement program logic.

I would encourage you to learn how to use RTOS-es, as they make similar tasks much easier and have IPC mechanisms implemented (so you will not have to reinvent the wheel) or implement complicated state machines in your main loop.

0___________
  • 60,014
  • 4
  • 34
  • 74
  • I've tried FREERTOS, however I was running in many problems. that RTOS-es is not on my list (using stm32f303re in the "middleware and software packs" tab). All I need is basically read mavlink from a uart port and forward it to another port depending on the message. I'm relatively new to STM32, can i install other OS that are not on the list? – João Ferreira Jul 31 '23 at 12:36
  • @JoãoFerreira DMA requires async programming and your program logic is invalid. For you read blocking in the main loop – 0___________ Jul 31 '23 at 13:51
  • What would you do if it was you? Do you think I should use freeRTOS? – João Ferreira Jul 31 '23 at 14:08
  • @JoãoFerreira it is up to you. I almost always use RTOS – 0___________ Jul 31 '23 at 15:00