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

piolib: please add API to access the txstall register & other FDEBUG registers #114

Open
jepler opened this issue Jan 15, 2025 · 4 comments

Comments

@jepler
Copy link

jepler commented Jan 15, 2025

Sometimes it's necessary to wait for a txstall, not just tx fifo drain, before performing some other action. For instance, to implement transmit-only SPI with a GPIO CS pin, you need to wait for the last bit of SPI data to actually be transmitted before deasserting CS.

@jepler jepler changed the title piolib: add API to access the txstall register & other FDEBUG registers piolib: please add API to access the txstall register & other FDEBUG registers Jan 15, 2025
@pelwell
Copy link
Collaborator

pelwell commented Jan 16, 2025

Hi Jeff, my head is temporarily out of PIO space, but I'll consider this and #115 when it returns.

@pelwell
Copy link
Collaborator

pelwell commented Jan 17, 2025

TXSTALL appears along with other flags (RXSTALL. TXOVER and RXUNDER) in the FDEBUG register. There is currently no accessor function, so I feel free to come up with something new - ideally one that automatically selects the correct flags for the current/specified SM.

How do you feel about the following:

    uint pio_sm_get_flags(PIO pio, uint sm, uint flags, bool clear);
    uint pio_sm_wait_flags(PIO pio, uint sm, uint flags, bool clear, uint timeout_us);

flags is a bit mask of abstract flags. As you've probably guessed, clear allows any matching flags to be cleared. The return value is the sum of the flags which were set. pio_sm_wait_flags causes the return to block until any of the specified flags (is "events" a better name?) is true, or the timeout expires. pio_sm_get_flags is effectively pio_sm_wait_flag with a timeout of 0, and will probably be implemented as such. A return value of 0 indicates the timeout expired before any flags were set.

@jepler
Copy link
Author

jepler commented Jan 17, 2025

Here's what we do in CircuitPython on rp2 around detecting completion of a transfer:

        // Clear the stall bit so we can detect when the state machine is done transmitting.
        self->pio->fdebug = stall_mask;
    }
    // Wait for the state machine to finish transmitting the data we've queued
    // up.
    if (tx) {
        while (!pio_sm_is_tx_fifo_empty(self->pio, self->state_machine) ||
               (self->wait_for_txstall && (self->pio->fdebug & stall_mask) == 0)) {
            RUN_BACKGROUND_TASKS;
            if (self->user_interruptible && mp_hal_is_interrupted()) {
                break;
            }
        }
    }

the first bit would be pio_sm_get_flags(self->pio, self->state_machine, PIO_FLAG_TXSTALL, true); and the second would be pio_sm_get_flags(self->pio, self->state_machine, PIO_FLAG_TXSTALL, false). Because we need to poll for other events, we probably would't use a timeout_us variant.

We don't actually seem to use any other FDEBUG bits than TXSTALL and RXSTALL fwiw

@pelwell
Copy link
Collaborator

pelwell commented Jan 17, 2025

I'd already decided to include a pio_sm_clear_flags API function, however it is implemented.

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

No branches or pull requests

2 participants