Multiple struct instances with work threads

I have an application I am working on, and I created a custom structure rx_servo_t. The structure is meant to provide methods for controlling some off board motors via GPIO and PWMs. When initialized, the structure launches a work thread that monitors the state of the structure. When I have one instance of the struct, my application seems to work as intended. However I want to instantiate multiple instances of this struct, and that is where I am seeing issues.

Top of main.c where I instantiate the structs Dose and Valve Servo

rx_servo_t dose_servo = {
        .name = "Dose Servo",
        .motor.name = "Dose Motor",
        .encoder.name = "Dose Encoder",
};
rx_servo_t valve_servo = {
        .name = "Valve Servo",
        .motor.name = "Valve Motor",
        .encoder.name = "Valve Encoder",
};

Inside main function where I initialize the structs, The 5 second delay is for demonstrating what is happening in the logging.

int main(void)
{

        rx_servo_init(&dose_servo, &dose_enc_a, &dose_enc_b, &dose_motor_dir, &dose_motor_spd);
        k_sleep(K_MSEC(5000));
        rx_servo_init(&valve_servo, &valve_enc_a, &valve_enc_b, &valve_motor_dir, &valve_motor_spd);
        ...

The initialization function

void rx_servo_init(rx_servo_t *svo, const struct gpio_dt_spec *enc_a, const struct gpio_dt_spec *enc_b,
                   const struct gpio_dt_spec *mtr_ph, const struct pwm_dt_spec *mtr_en)
{
    LOG_INF("Initializing %s servo", svo->name);
    servo = svo;
    // strncpy(servo->name, "RX Servo", 32);
    rx_encoder_init(&servo->encoder, enc_a, enc_b);
    rx_motor_init(&servo->motor, mtr_ph, mtr_en);

    servo->home = rx_servo_home;                              // Assign the home function to the servo object
    servo->move = rx_servo_move;                              // Assign the move function to the servo object
    servo->state = SERVO_LOST;                                // Set the initial state of the servo
    servo->motor.stop();                                      // Stop the motor
    servo->motor.set_period(RX_SERVO_MOTOR_PERIOD_USEC);      // Set the period of the motor
    servo->motor.set_dutycycle(RX_SERVO_MOTOR_MIN_DUTYCYCLE); // Set the initial duty cycle
    k_work_init(&svo->work, rx_servo_work_handler);           // Initialize the work item
    k_timer_init(&svo->timer, rx_servo_timer_handler, NULL);  // Initialize the timer
    k_timer_start(&svo->timer, K_MSEC(RX_SERVO_PERIOD),
                  K_MSEC(RX_SERVO_PERIOD));
    if(servo->initialized == 1)
    {
        LOG_ERR("Servo %s already initialized", svo->name);
        return;
    }
    servo->initialized = 1; // Set the initialized flag
    LOG_INF("Initializing servo %s complete", svo->name);
}

At the start of the work handler, I print a log message.

void rx_servo_work_handler(struct k_work *work)
{
    rx_servo_t *svo = CONTAINER_OF(work, rx_servo_t, work);
    LOG_INF("%s Servo work handler running", servo->name);

The output of my application is as follows. Logging starts as expected with the first instance, but after the 5 second delay, there are then 2 log messages for the second instance.

Thanks in advance for any assistance.

Related