Home > Software engineering >  why does my mbed rtos::thread run a function multiple times
why does my mbed rtos::thread run a function multiple times

Time:04-19

I'm developing an embedded system on a NUCLEO-F303RE, I'm a using rtos::thread to start a function which needs to adjust a motor speed according to another motor's speed. To do this I'm trying to get the speed from the motor by using the following code:

       Motor::ErrorCode Motor::getRegister(Motor::MotorID motor, Register reg,
                                        uint8_t *data, uint8_t dataLength)
    {
        uint8_t responseBuffer[8];
        sendCommand(motor, GET_REGISTER, reinterpret_cast<const uint8_t *>(&reg), 1, responseBuffer);
        ErrorCode error = responseBufferToError(responseBuffer);
        if (error == NO_ERROR)
        {
            for (int i = 0; i < dataLength && i < responseBuffer[1]; i  )
            {
                data[i] = responseBuffer[2   i];
            }
        }
        System::getInstance()->debugMessage("Motor", "getRegister: %d",data[0]);
        return error;
    }

When putting debug messages inside of the code above I can see that the code keeps looping while also getting to the return.

This piece of code is inside of the getSpeed method from the motorController in the code below. Because of the loop it doesn't exit getSpeed, which in turn blocks execution of the other code.

    if (supportMotor == MOTORID_1)
            {
                mainMotor = MOTORID_2;
                motorController->getSpeed(mainMotor, _speed);
                _error = motors[mainMotor - 1].getLastErrorCode();
                if (_error == NO_ERROR)
                {
                    // Set support motor speed
                    motorController->setMotorSpeed(supportMotor, _speed * MOTOR_GEAR_RATIO);
                    _error = motors[supportMotor - 1].getLastErrorCode();
                    if (_error != NO_ERROR)
                    {
                        motorController->setNeedsGearing(false);
                        thread->join();
                    }
                }
                else
                {
                    motorController->setNeedsGearing(false);
                    thread->join();
                }
            }

The motorcontroller itself isn't throwing any errors. This code has been tested outside of a thread, this worked as expected. My question is why does this work outside of the loop but not when placed inside.

Edit: This is all the code called between getSpeed and the problem. This does inflate the question, but it gives transparency on the functions that are being called

getSpeed:

    bool MotorController::getSpeed(uint8_t motor, int32_t &speed)
    {
        if (motor != MOTORID_1 && motor != MOTORID_2)
            return false;
        return _motors[motor - 1].getMeasuredSpeed(speed, Motor::MOTOR_1);
    }

getMeasuredSpeed:

bool getMeasuredSpeed(int32_t &measuredSpeed, MotorID motor = LAST_MOTOR) { return getRegisterS32(motor, SPEED_MEASURED, measuredSpeed) == NO_ERROR; }

getRegister32:

    Motor::ErrorCode Motor::getRegisterS32(Motor::MotorID motor, Motor::Register reg,
                                           int32_t &data)
    {
        return getRegister(motor, reg, reinterpret_cast<uint8_t *>(&data), 4);
    }

CodePudding user response:

The mbed thread handler will keep running the threads for you, until the thread is terminated, read this link to the docs link

CodePudding user response:

What I sense after looking at the code is:

  • getSpeed() is taking more time than how much a thread is given.
  • Usually a thread runs for few milli-seconds (say X).
  • If any logic takes more time than X, then the thread is terminated.
  • When the thread is give a chance to run again, it executes from beginning.
  • In order to synchronize this with threads, we usually use signals.

Code written for a thread is different from a code written for while(1). For threads, we can use something like this:

/** Assume this function is called by thread. **/
thread_function()
{
    /** We call a function which might take time and then wait for a 
    signal. **/
    time_taking_fn();

    wait_for_signal_s();

    /** This allows the thread to get suspended. When the time taking
    logic sets a signal, the thread gets to know and executes the rest
    of logic. **/ 
}

/** The time taking function, which was called, will set signal when it 
is done with its logic. **/
time_taking_fn()
{
    /** Do something */
    set_signal_s();
}
  • Related