Best practice to keep main() in embedded systems
If you're concerned that code for a simple switch() based state machine (SM) will become untidy, you can split it into smaller subroutines.

void do_state_s1() {
    // stuff
    if ( /* certain  contidition */ ) {
        g_iState = STATE_S2;  // transition to another state
    }
}

void do_state_s2()  {
    // other stuff
    if ( /* some other condition */ ) {
        g_iState = STATE_S1;
    }
}

void do_state_machine() {
    switch (g_iState) {
    case STATE_S1:
        do_state_s1();
        break;

    case STATE_S2:
        do_state_s2();
        break;
    };
}

void main() {
    g_iState = STATE_S1;        // initialize the SM

    while (1) {
        do_state_machine();
    }
}