UART random freezes

I am using a 24v V3.6 odrive with razoredge firmware.
The Arduino code I used is basically the example code with small modifications. The code is attached at the end of the post.
Symptom:
I can check the voltage and encoder readings on Arduino just fine. But the motor freezes randomly when I try to set its positions via UART. Most of the time, the motor follows the position command for a while and freezes randomly.
I tried two different commands to set the motor position. Both of them would stall the odrive randomly.

Serial1 << "p " << 1 << " " << pos_m1 << '\n';
Serial1 << "w axis" << 1 << ".controller.input_pos " << pos_m1 << '\n';

When frozen, Odrive does not respond to any odrivetool commands or UART inputs from the Arduino. The only way to reset is to cut power and reboot.
Sending the motor position at different frequency doesn’t seem to help. I have tried 200Hz (delay(5)) and 20Hz (delay(50)).
Does anyone else have the same problem? What’s the cause of the problem? Any help is appreciated!

EDIT:
https://discourse.odriverobotics.com/t/uart-communication-maximum-frequency-timeout/844/2
This post suggests some changes in the firmware. Will try it later on.

#include <SoftwareSerial.h>
#include <ODriveArduino.h>

// Printing with stream operator
template<class T> inline Print& operator <<(Print &obj,     T arg) { obj.print(arg);    return obj; }
template<>        inline Print& operator <<(Print &obj, float arg) { obj.print(arg, 4); return obj; }

// Serial to the ODrive
// Note: you must also connect GND on ODrive to GND on Arduino!

// ODrive object
ODriveArduino odrive(Serial1);

void setup() {
  // ODrive uses 115200 baud
  Serial1.begin(115200);

  // Serial to PC
  Serial.begin(115200);
  while (!Serial) ; // wait for Arduino Serial Monitor to open

  Serial.println("ODriveArduino");
  Serial.println("Setting parameters...");

  // In this example we set the same parameters to both motors.
  // You can of course set them different if you want.
  // See the documentation or play around in odrivetool to see the available parameters
  for (int axis = 0; axis < 2; ++axis) {
    Serial1 << "w axis" << axis << ".controller.config.vel_limit " << 22000.0f << '\n';
    Serial1 << "w axis" << axis << ".motor.config.current_lim " << 11.0f << '\n';
    // This ends up writing something like "w axis0.motor.config.current_lim 10.0\n"
  }

  Serial.println("Ready!");
  Serial.println("Send the character '0' to set odrive to idle");
  Serial.println("Send the character '1' to set odrive to calibration");
  Serial.println("Send the character '2' to set odrive to closed loop control");
  Serial.println("Send the character 's' to exectue test move");
  Serial.println("Send the character 'b' to read bus voltage");
  Serial.println("Send the character 'p' to read motor positions in a 10s loop");
}

void loop() {

  if (Serial.available()) {
    char c = Serial.read();

    // set odrive to idle
    if (c == '0') {
      Serial1 << "w axis" << 1 << ".requested_state " << 1 << '\n';
      c = '3';
    }
    // Run calibration sequence
    if (c == '1') {
      Serial1 << "w axis" << 1 << ".requested_state " << 3 << '\n';
      c = '3';
    }
    // set odrive to closed loop ctrl
    if (c == '2') {
      Serial1 << "w axis" << 1 << ".requested_state " << 8 << '\n';
      c = '3';
    }

    // Sinusoidal test move
    if (c == 's') {
      Serial.println("Executing test move");
      for (float ph = 0.0f; ph < 6.28318530718f; ph += 0.01f) {
        float pos_m1 = 20000.0f * sin(ph);
//        Serial1 << "w axis" << 1 << ".controller.input_pos " << pos_m1 << '\n';
        Serial1 << "p " << 1 << " " << pos_m1 << '\n';
        delay(10);
      }
    }

    // Read bus voltage
    if (c == 'b') {
      Serial1 << "r vbus_voltage\n";
      Serial << "Vbus voltage: " << odrive.readFloat() << '\n';
    }

    // print motor positions in a 10s loop
    if (c == 'p') {
      static const unsigned long duration = 10000;
      unsigned long start = millis();
      while(millis() - start < duration) {
        for (int motor = 0; motor < 2; ++motor) {
          Serial1 << "r axis" << motor << ".encoder.pos_estimate\n";
          Serial << odrive.readFloat() << '\t';
        }
        Serial << '\n';
      }
    }
  }
}

I just tried modifying the firmware according to the post below. And I can’t read anything from the ODrive via Arduino anymore… But I can still access them on odrivetool.
Help!!!

https://discourse.odriverobotics.com/t/uart-communication-maximum-frequency-timeout/844

Tested a few more things.
Before testing, I reverted the changes mentioned in
https://discourse.odriverobotics.com/t/uart-communication-maximum-frequency-timeout/844/2
Then, I changed the buffer size defined in interface_uart.cpp.

#define UART_TX_BUFFER_SIZE 1024
#define UART_RX_BUFFER_SIZE 1024

After that, I tried to set motor position with different serial commands. And it appears that odrive is less likely to stall when the serial messages are long.
When I send two consecutive messages via serial like it is shown in the code below, odrive can operate without any problem.

      Serial.println("Executing test move");
      float ph = 0.0f;
      while (ph <= 6.28f) {
        float pos_m1 = 20000.0f * sin(ph);
        Serial1 << "p " << 1 << " " << pos_m1 << '\n';
        Serial1 << "r axis" << 1 << ".encoder.pos_estimate\n";
        Serial << odrive.readFloat() << '\t' << pos_m1 << '\n';
        ph = ph + 0.01f;
        if (ph > 6.28f){
          ph = 0.0f;
        }
        delay(3);
      }

Basically, the code asks the motor to spin forever until I manually stop Arduino sending the message. It also asks the odrive to send back the encoder measurements. I let it ran for 10 minutes and everything works fine: motor spins as expected, odrive doesn’t stall.

However, the random freezes come back when I reduces the length of the serial message to:

Serial1 << "w axis" << 1 << ".controller.input_pos " << pos_m1 << '\n';

or

 Serial1 << "p " << 1 << " " << pos_m1 << '\n';

I didn’t do any statistics, but I think the shortest command (the one starts with p) has the highest fail probability. And that’s weird, since that’s basically what’s done in the ODriveArduino library:

void ODriveArduino::SetPosition(int motor_number, float position, float velocity_feedforward, float current_feedforward) {
    serial_ << "p " << motor_number  << " " << position << " " << velocity_feedforward << " " << current_feedforward << "\n";
}