Skip to content

Implement parallel slave configuration (Steps 2–4)#154

Merged
sittner merged 2 commits intoparallel-slave-configfrom
copilot/implement-parallel-slave-configuration
Mar 2, 2026
Merged

Implement parallel slave configuration (Steps 2–4)#154
sittner merged 2 commits intoparallel-slave-configfrom
copilot/implement-parallel-slave-configuration

Conversation

Copy link
Copy Markdown
Contributor

Copilot AI commented Mar 2, 2026

Steps 2–4 of the parallel slave configuration design, enabling all slaves requiring configuration to be driven concurrently rather than sequentially one at a time.

Changes

fsm_slave_config.h — Expose ec_fsm_slave_config_running()

  • Promoted internal forward-declaration to public API so fsm_slave can query config FSM liveness.

fsm_slave.h / fsm_slave.c — Embed config FSM in each slave FSM

  • Each ec_fsm_slave_t now owns a full config FSM stack: fsm_slave_config, fsm_change, fsm_coe_config, fsm_soe_config, fsm_eoe_config, fsm_pdo.
  • Added config_requested:1 / config_running:1 bitfields.
  • ec_fsm_slave_exec() runs the embedded config FSM first (consuming the datagram) before falling through to request handling.
  • New ec_fsm_slave_request_config() sets the config_requested flag; the FSM picks it up on the next execution cycle.

fsm_master.c — Delegate configuration in parallel

  • ec_fsm_master_action_configure() now iterates all slaves in a single pass, calling ec_fsm_slave_request_config() on every slave that needs it, then transitions to the new ec_fsm_master_state_wait_config state.
  • ec_fsm_master_state_wait_config() polls config_requested/config_running across all slaves; releases config_busy and wakes config_queue once all are done.

master.c — Schedule config-active slaves onto external datagrams

  • ec_master_exec_slave_fsms() pick-up loop now includes slaves with config_requested or config_running (previously only ec_fsm_slave_is_ready() slaves were scheduled).
if (ec_fsm_slave_is_ready(&master->fsm_slave->fsm)
        || master->fsm_slave->fsm.config_requested
        || master->fsm_slave->fsm.config_running) {
Original prompt

Overview

Implement the remaining steps (2, 3, 4) described in PARALLEL_SLAVE_CONFIG_IMPL.md (at commit f295ad8b80ee9018eeb024e26f11d3b6edb6bcbb on branch parallel-slave-config) to enable parallel slave configuration in the IgH EtherCAT Master.

Step 1 is already completefsm_slave_config already uses external datagram/FSM pointers. The remaining work is Steps 2–4.

Read PARALLEL_SLAVE_CONFIG_IMPL.md on the parallel-slave-config branch carefully — it contains the exact code snippets and instructions for each step. Follow it precisely.


Step 2: Add Configuration State Machine to fsm_slave

Files: master/fsm_slave.h, master/fsm_slave.c

2.1 Update master/fsm_slave.h

Add new includes at the top (after existing includes):

#include "fsm_slave_config.h"
#include "fsm_change.h"
#include "fsm_pdo.h"

Add the following new members to struct ec_fsm_slave (between the existing request pointers and the existing sub-FSMs):

    // Configuration state machine and sub-FSMs
    ec_fsm_slave_config_t fsm_slave_config;
    ec_fsm_change_t fsm_change;
    ec_fsm_coe_t fsm_coe_config;      // Separate from request handling
    ec_fsm_soe_t fsm_soe_config;      // Required by ec_fsm_slave_config_init
#ifdef EC_EOE
    ec_fsm_eoe_t fsm_eoe_config;      // Required by ec_fsm_slave_config_init
#endif
    ec_fsm_pdo_t fsm_pdo;

    // Configuration request flags
    unsigned int config_requested:1;
    unsigned int config_running:1;

Add new function declarations:

void ec_fsm_slave_request_config(ec_fsm_slave_t *);
int ec_fsm_slave_config_success(const ec_fsm_slave_t *);

2.2 Update master/fsm_slave.c

In ec_fsm_slave_init(), add initialization of configuration flags and sub-FSMs before the existing ec_fsm_coe_init/ec_fsm_foe_init/ec_fsm_soe_init calls:

    // Initialize configuration flags
    fsm->config_requested = 0;
    fsm->config_running = 0;

    // Initialize configuration sub-FSMs
    ec_fsm_change_init(&fsm->fsm_change, NULL);
    ec_fsm_coe_init(&fsm->fsm_coe_config);
    ec_fsm_soe_init(&fsm->fsm_soe_config);
    ec_fsm_pdo_init(&fsm->fsm_pdo, &fsm->fsm_coe_config);
#ifdef EC_EOE
    ec_fsm_eoe_init(&fsm->fsm_eoe_config);
#endif
    ec_fsm_slave_config_init(&fsm->fsm_slave_config, NULL,
                              &fsm->fsm_change, &fsm->fsm_coe_config,
                              &fsm->fsm_soe_config, &fsm->fsm_pdo,
                              &fsm->fsm_eoe_config);

IMPORTANT: Check how ec_fsm_change_init is called in fsm_master.c on this branch to determine the correct number of parameters (it may take a datagram pointer). Use the same pattern but pass NULL.

IMPORTANT: The ec_fsm_slave_config_init call must match the actual signature in fsm_slave_config.h on the branch:

void ec_fsm_slave_config_init(ec_fsm_slave_config_t *, ec_datagram_t *,
        ec_fsm_change_t *, ec_fsm_coe_t *, ec_fsm_soe_t *, ec_fsm_pdo_t *,
        ec_fsm_eoe_t *);

Note it takes 7 parameters (fsm, datagram, change, coe, soe, pdo, eoe). When EC_EOE is not defined, check if there's a conditional version or if the EoE parameter is always required.

In ec_fsm_slave_clear(), add cleanup of configuration sub-FSMs before the existing cleanup:

    // Clear configuration sub-FSMs
    ec_fsm_slave_config_clear(&fsm->fsm_slave_config);
    ec_fsm_change_clear(&fsm->fsm_change);
    ec_fsm_coe_clear(&fsm->fsm_coe_config);
    ec_fsm_soe_clear(&fsm->fsm_soe_config);
    ec_fsm_pdo_clear(&fsm->fsm_pdo);
#ifdef EC_EOE
    ec_fsm_eoe_clear(&fsm->fsm_eoe_config);
#endif

Add two new functions:

void ec_fsm_slave_request_config(ec_fsm_slave_t *fsm)
{
    fsm->config_requested = 1;
}

int ec_fsm_slave_config_success(const ec_fsm_slave_t *fsm)
{
    return !fsm->config_running && !fsm->config_requested;
}

Modify ec_fsm_slave_exec() to handle configuration before the existing state machine execution. Add at the beginning of the function:

    int datagram_used = 0;

    // Handle configuration if requested
    if (fsm->config_requested && !fsm->config_running) {
        fsm->config_requested = 0;
        fsm->config_running = 1;
        fsm->fsm_slave_config.datagram = datagram;
        ec_fsm_slave_config_start(&fsm->fsm_slave_config, fsm->slave);
    }

    if (fsm->config_running) {
        fsm->fsm_slave_config.datagram = datagram;
        if (ec_fsm_slave_config_exec(&fsm->fsm_slave_config)) {
            datagram_used = 1;
        }
        if (!ec_fsm_slave_config_running(&fsm->fsm_slave_config)) {
            fsm->config_running = 0;
            EC_SLAVE_DBG(fsm->slave, 1, "Configuration finished.\n");
        }
        if (datagram_used) {
            fsm->datagram = datagram;
            return 1;
        }
    }

Then continue with the existing fsm->state(fsm, datagram); call and the rest of the existing logic.

2.3 Expose ec_fsm_slave_config_running() in `...

This pull request was created from Copilot chat.


🔒 GitHub Advanced Security automatically protects Copilot coding agent pull requests. You can protect all pull requests by enabling Advanced Security for your repositories. Learn more about Advanced Security.

Co-authored-by: sittner <1475582+sittner@users.noreply.github.com>
Copilot AI changed the title [WIP] Add remaining steps for parallel slave configuration Implement parallel slave configuration (Steps 2–4) Mar 2, 2026
@sittner sittner marked this pull request as ready for review March 2, 2026 09:59
@sittner sittner merged commit 770ebbc into parallel-slave-config Mar 2, 2026
@sittner sittner deleted the copilot/implement-parallel-slave-configuration branch March 4, 2026 08:20
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants