QSPI I/O¶
QSPI I/O API¶
The following structures and functions are used for low-level QSPI I/O.
-
enum qspi_io_sample_edge_t¶
Enum type used to set which SCLK edge SIO is sampled on.
Values:
-
enumerator qspi_io_sample_edge_rising¶
Sample SIO on the rising edge
-
enumerator qspi_io_sample_edge_falling¶
Sample SIO on the falling edge
-
enumerator qspi_io_sample_edge_rising¶
-
enum qspi_io_source_clock_t¶
Enum type used to set which of the two clock sources SCLK is derived from.
Values:
-
enumerator qspi_io_source_clock_ref¶
SCLK is derived from the 100 MHz reference clock
-
enumerator qspi_io_source_clock_xcore¶
SCLK is derived from the core clock
-
enumerator qspi_io_source_clock_ref¶
-
enum qspi_io_transfer_mode_t¶
Enum type used to specify whether or not nibbles should be swapped during transfers.
Values:
-
enumerator qspi_io_transfer_normal¶
Do not swap nibbles
-
enumerator qspi_io_transfer_nibble_swap¶
Swap nibbles
-
enumerator qspi_io_transfer_normal¶
-
enum qspi_io_transaction_type_t¶
Enum type used to specify whether the next transaction will be a full speed QSPI transaction with dummy cycles, or a lower speed SPI read transaction without dummy cycles.
Values:
-
enumerator qspi_io_full_speed¶
The transaction will be full speed with dummy cycles
-
enumerator qspi_io_spi_read¶
The transaction will be low speed without dummy cycles
-
enumerator qspi_io_full_speed¶
-
inline uint32_t qspi_io_byte_to_mosi(uint32_t x)¶
This function should only be called internally by qspi_io_mosi_out(). It performs the same transformation as QSPI_IO_BYTE_TO_MOSI() but also integrates the byte reversal and nibble swap performed by qspi_io_words_out().
- Parameters
x – The byte to send out to MOSI.
- Returns
the word to output to SIO.
-
inline uint32_t qspi_io_miso_to_byte(uint32_t x)¶
This function should only be called internally by qspi_io_miso_in().
When reading in a single byte in SPI mode, the word that is received on SIO needs to be transformed such that bit one from each nibble (which corresponds to SIO1, or MISO) is shifted into the correct bit position.
- Parameters
x – The word received on SIO.
- Returns
the byte received on MISO.
-
inline uint32_t qspi_io_nibble_swap(uint32_t word)¶
This function swaps the nibbles in each of the four bytes of
word
.- Parameters
word – The word to nibble swap.
- Returns
the nibble swapped word.
-
inline void qspi_io_start_transaction(qspi_io_ctx_t *ctx, uint32_t first_word, size_t len, qspi_io_transaction_type_t transaction_type)¶
Begins a new QSPI I/O transaction by starting the clock, asserting CS, and sending out the first word which is typically a command.
Note
If more words or bytes need to be sent or received as part of this transaction, then the appropriate functions will need to be called immediately following this one. For example, qspi_io_bytes_out() then qspi_io_sio_direction_input() then qspi_io_bytes_in(). The “out” or “in” instruction in each must be executed within eight SCLK cycles of the preceding one, including the OUT instruction in qspi_io_start_transaction(). Some analysis may be necessary depending on the frequency of SCLK. These functions are all marked as inline to help keep them closer together by removing the overhead associated with function calls and to allow better optimization.
Note
It is likely not possible to follow an input with an output within a single transaction unless the frequency of SCLK is sufficiently slow. Fortunately in practice this rarely, if ever, required.
- Parameters
ctx – Pointer to the QSPI I/O context.
first_word – The first word to output.
len – The total number of clock cycles in the transaction. CS will at some point during the transaction be setup to deassert automatically after this number of cycles.
transaction_type – Set to qspi_io_spi_read if the transaction will be a SPI read with no dummy cycles. This may run at a slower clock frequency in order to turn around SIO from output to input in time. Otherwise set to qspi_io_full_speed.
-
inline void qspi_io_bytes_out(const qspi_io_ctx_t *ctx, const qspi_io_transfer_mode_t transfer_mode, const uint8_t *data, size_t len)¶
Outputs a byte array to the QSPI interface. The byte array must start on a 4-byte boundary. This call must be made in time such that its OUT instruction executes within 8 SCLK cycles of the previous OUT instruction.
- Parameters
ctx – Pointer to the QSPI I/O context.
transfer_mode – Can be either qspi_io_transfer_normal or qspi_io_transfer_nibble_swap. When qspi_io_transfer_nibble_swap, each byte transferred out is nibble swapped. Because the data is inherently sent out nibble swapped over the port, setting this to qspi_io_transfer_nibble_swap actually removes a nibble swap operation.
data – Pointer to the byte array to output. This MUST begin on a 4-byte boundary.
len – The number of bytes in
data
to output.
-
inline void qspi_io_words_out(const qspi_io_ctx_t *ctx, const qspi_io_transfer_mode_t transfer_mode, const uint32_t *data, size_t len)¶
Outputs a word array to the QSPI interface. This call must be made in time such that its OUT instruction executes within 8 SCLK cycles of the previous OUT instruction.
- Parameters
ctx – Pointer to the QSPI I/O context.
transfer_mode – Can be either qspi_io_transfer_normal or qspi_io_transfer_nibble_swap. When qspi_io_transfer_nibble_swap, each byte transferred out is nibble swapped. Because the data is inherently sent out nibble swapped over the port, setting this to qspi_io_transfer_nibble_swap actually removes a nibble swap operation.
data – Pointer to the word array to output.
len – The number of words in
data
to output.
-
inline void qspi_io_mosi_out(const qspi_io_ctx_t *ctx, const qspi_io_transfer_mode_t transfer_mode, const uint8_t *data, size_t len)¶
Outputs a byte array to the QSPI interface over the single data line MOSI (SIO0). This call must be made in time such that its OUT instruction executes within 8 SCLK cycles of the previous OUT instruction.
- Parameters
ctx – Pointer to the QSPI I/O context.
transfer_mode – Can be either qspi_io_transfer_normal or qspi_io_transfer_nibble_swap. When qspi_io_transfer_nibble_swap, each byte transferred out is nibble swapped.
data – Pointer to the byte array to output.
len – The number of words in
data
to output.
-
inline void qspi_io_sio_direction_input(qspi_io_ctx_t *ctx)¶
This must be called to change the direction of SIO from output to input before calling either qspi_io_bytes_in() or qspi_io_words_in(). This call must be made in time such that the call to port_set_buffered() completes before the sample edge of SCLK shifts in the first nibble of the next data word to be read. This also will setup CS to deassert at the end of the transaction while waiting for the previous output to complete.
Note
This is probably the most fragile function. Ensure that the port direction is turned around on time, and that the subsequent read IN instruction executes on time, by inspecting a VCD trace with both ports and instructions.
- Parameters
ctx – Pointer to the QSPI I/O context.
-
inline void qspi_io_bytes_in(const qspi_io_ctx_t *ctx, const qspi_io_transfer_mode_t transfer_mode, uint8_t *data, uint32_t start_time, size_t len)¶
Inputs a byte array from the QSPI interface. The byte array must start on a 4-byte boundary. qspi_io_sio_direction_input() must have been called previously. This call must be made in time such that its IN instruction executes before
start_time
.Note
The number of bytes input may be any number. However, if it is NOT a multiple of four, then this likely will need to be the last call in the transaction. This is because the shorter length of the last input chunk plus the extra overhead required to deal with the sub-word accesses will not allow subsequent I/O to keep up unless the SCLK frequency is significantly slower than the core clock.
- Parameters
ctx – Pointer to the QSPI I/O context.
transfer_mode – Can be either qspi_io_transfer_normal or qspi_io_transfer_nibble_swap. When qspi_io_transfer_nibble_swap, each byte transferred in is nibble swapped. Because the data is inherently received nibble swapped over the port, setting this to qspi_io_transfer_nibble_swap actually removes a nibble swap operation.
data – Pointer to the byte array to save the received data to. This MUST begin on a 4-byte boundary.
start_time – The port time, relative to the beginning of the transfer, at which to input the first group of four bytes. This must line up with the last nibble of the fourth byte. If
len
is less than four, then it must line up with the last nibble of the last byte.len – The number of bytes to input.
-
inline void qspi_io_words_in(const qspi_io_ctx_t *ctx, const qspi_io_transfer_mode_t transfer_mode, uint32_t *data, uint32_t start_time, size_t len)¶
Inputs a word array from the QSPI interface. qspi_io_sio_direction_input() must have been called previously. This call must be made in time such that its IN instruction executes before
start_time
.- Parameters
ctx – Pointer to the QSPI I/O context.
transfer_mode – Can be either qspi_io_transfer_normal or qspi_io_transfer_nibble_swap. When qspi_io_transfer_nibble_swap, each byte transferred in is nibble swapped. Because the data is inherently received nibble swapped over the port, setting this to qspi_io_transfer_nibble_swap actually removes a nibble swap operation.
data – Pointer to the word array to save the received data to.
start_time – The time, relative to the beginning of the transfer, at which to input the first word. This must line up with the last nibble of the first word.
len – The number of words to input.
-
inline void qspi_io_miso_in(const qspi_io_ctx_t *ctx, const qspi_io_transfer_mode_t transfer_mode, uint8_t *data, uint32_t start_time, size_t len)¶
Inputs a byte array from the QSPI interface over the single data line MISO (SIO1). qspi_io_sio_direction_input() must have been called previously. This call must be made in time such that its IN instruction executes before
start_time
.- Parameters
ctx – Pointer to the QSPI I/O context.
transfer_mode – Can be either qspi_io_transfer_normal or qspi_io_transfer_nibble_swap. When qspi_io_transfer_nibble_swap, each byte transferred in is nibble swapped.
data – Pointer to the byte array to save the received data to.
start_time – The time, relative to the beginning of the transfer, at which to input the first byte. This must line up with the last bit of the first byte.
len – The number of words to input.
-
inline void qspi_io_miso_poll(const qspi_io_ctx_t *ctx, const uint8_t mask, const uint8_t val, uint32_t start_time)¶
Polls the SPI interface by repeatedly receiving a byte over MISO until a specified condition is met. For each time the received byte does not meet the condition, the deassertion of CS is extended by eight SCLK cycles. qspi_io_sio_direction_input() must have been called previously. This call must be made in time such that its IN instruction executes before
start_time
.- Parameters
ctx – Pointer to the QSPI I/O context.
mask – The bitmask to apply to the received byte before comparing it to
val
;val – The value that the received byte, masked with
mask
, must match before returning.start_time – The time, relative to the beginning of the transfer, at which to input the first byte. This must line up with the last bit of the first byte.
-
inline void qspi_io_end_transaction(const qspi_io_ctx_t *ctx)¶
This sets up CS to deassert at the end of the transaction if it has not already, waits for the current QSPI transaction to complete, and then stops SCLK.
- Parameters
ctx – Pointer to the QSPI I/O context.
-
void qspi_io_deinit(const qspi_io_ctx_t *ctx)¶
This disables and frees the clock block and all the ports associated with the QSPI I/O interface.
- Parameters
ctx – Pointer to the QSPI I/O context. This should have been previously initialized with qspi_io_init().
-
void qspi_io_init(const qspi_io_ctx_t *ctx, qspi_io_source_clock_t source_clock)¶
This sets up the clock block and all the ports associated with the QSPI I/O interface. This must be called first prior to any other QSPI I/O function.
- Parameters
ctx – Pointer to the QSPI I/O context. This must be initialized with the clock block and ports to use.
source_clock – Set to qspi_io_source_clock_ref to use the 100 MHz reference clock as the source for SCLK. Set to qspi_io_source_clock_xcore to use the xcore clock.
-
QSPI_IO_BYTE_TO_MOSI(x)¶
This macro may be used when sending out bytes that are only transmitted over the single data line MOSI (SIO0). The returned word should be transmitted using either qspi_io_start_transaction() or qspi_io_words_out(). Typically the byte argument to this macro is a constant known at compile time, like commands, as the compiler can perform this computation at compile time. For arrays of data, it may be more appropriate to use qspi_io_mosi_out() which more efficiently computes this transformation at run time on the fly.
When writing a single byte out in SPI mode, the byte needs to be transformed such that each nibble in the word that is sent out on SIO contains one bit from the byte in bit 0 (which corresponds to SIO0, or MOSI).
- Parameters
x – The byte to send out to MOSI.
-
QSPI_IO_SETC_PAD_DELAY(n)¶
-
QSPI_IO_RESOURCE_SETCI(res, c)¶
-
QSPI_IO_RESOURCE_SETC(res, r)¶
-
QSPI_IO_SETSR(c)¶
-
QSPI_IO_CLRSR(c)¶
-
struct qspi_io_ctx_t¶
- #include <qspi_io.h>
The context structure that must be passed to each of the qspi_io functions. Several of the members in this structure must be set by the application prior to calling either qspi_io_init() or qspi_io_start_transaction().