Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use JTAG to invoke offline mode #28

Merged
merged 11 commits into from
Oct 12, 2023

Conversation

mossmann
Copy link
Member

@mossmann mossmann commented Oct 9, 2023

From a user's perspective, FPGA configuration state transitions with Apollo currently look like:

image

(Transient states in blue automatically progress to a subsequent state.)

  • In "offline" mode the FPGA is in initialization triggered with the ECP5's PROGRAMN pin.
  • In "unconfigured" mode the FPGA is in initialization triggered by JTAG.
  • You can't avoid starting up from flash and going into user mode.
  • You can't program flash without going to offline or unconfigured mode first.
  • You can't configure from JTAG in offline mode.
  • You can't go to offline mode without subsequently configuring from flash.
  • You can't reconfigure from unconfigured mode (so the RESET button has no effect on the FPGA).
  • Configuration errors (e.g. empty flash) result in a state equivalent to unconfigured mode.

(I'm using "offline" and "unconfigured" as names for two separate states because that is what they are called in the code, more or less. Really the FPGA is both offline and unconfigured in both of those states, and the ECP5 documentation uses "offline mode" to refer to even more of the above states.)

Most of the drawbacks of the state machine are due to limitations of the offline and unconfigured modes. It would be desirable to have a single offline mode from which any state transition can be made. After some experimentation I determined that there is no way to support JTAG configuration from offline mode; once the PROGRAMN pin is pulled low, the only way to get back to user mode is through configuration from flash. It is possible, however, to support all state transitions from unconfigured mode which is invoked by JTAG.

This PR consolidates to a single "offline" mode (which is most similar to "unconfigured" mode above). The new state machine looks like:

image

  • In "offline" mode the FPGA is in initialization triggered by JTAG.
  • The PROGRAM button (on Cynthion only) allows the user to force offline mode.
  • All user actions have a result that is invariant to the previous state.
  • Configuration errors result in a state equivalent to offline mode.
  • Cynthion <r1.3.0 always configures from flash at power-on due to hardware/bootloader limitations.

Most of the complexity in the PR is in firmware which did not previously do JTAG things other than passing through JTAG operations from the host. In my tests it increased the size of the firmware binary by 172 bytes with GCC 10.3.

Previously reconfiguration could fail depending on the JTAG state. For
example, `apollo reconfiguration` did not work after `apollo
flash-info`.
- Separate implementation from vendor request handler.
- Remove redundant board-specific functions.
- Support configuration via both JTAG and SPI flash (or other
  board-specific method) from the same offline state.
- Remove redundant board-specific functions.
This is consistent with the other flash operations.
instead of letting them time out
@mossmann mossmann requested a review from mndza October 9, 2023 15:00
@mossmann
Copy link
Member Author

mossmann commented Oct 9, 2023

This also speeds up several apollo commands that were taking five seconds for no good reason.

Comment on lines +30 to +33
jtag_init();
jtag_go_to_state(STATE_TEST_LOGIC_RESET);
jtag_wait_time(2);
jtag_deinit();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What's the purpose of these blocks? Could you add a comment?
Besides that, I think the jtag_go_to_state(STATE_TEST_LOGIC_RESET) is redundant, as this is done implicitly in jtag_init().

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

jtag_init() does jtag_set_current_state(STATE_TEST_LOGIC_RESET), not jtag_go_to_state(STATE_TEST_LOGIC_RESET), so it isn't redundant, but perhaps jtag_init() really should call jtag_go_to_state(STATE_TEST_LOGIC_RESET). I've opened #29 to track that as a separate issue.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added the comments you suggested.

@mossmann mossmann requested a review from mndza October 11, 2023 23:06
Copy link
Contributor

@mndza mndza left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great!

@mndza mndza merged commit 1f84ce9 into greatscottgadgets:master Oct 12, 2023
3 checks passed
@mossmann mossmann deleted the jtag-offline branch October 12, 2023 12:50
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