XCORE SDK
XCORE Software Development Kit
Classes | Macros | Enumerations | Functions
hil_qspi_io

Classes

struct  qspi_io_ctx_t
 

Macros

#define QSPI_IO_BYTE_TO_MOSI(x)
 
#define QSPI_IO_SETC_PAD_DELAY(n)   (0x7007 | ((n) << 3))
 
#define QSPI_IO_RESOURCE_SETCI(res, c)   asm volatile( "setc res[%0], %1" :: "r" (res), "n" (c))
 
#define QSPI_IO_RESOURCE_SETC(res, r)   asm volatile( "setc res[%0], %1" :: "r" (res), "r" (r))
 
#define QSPI_IO_SETSR(c)   asm volatile("setsr %0" : : "n"(c));
 
#define QSPI_IO_CLRSR(c)   asm volatile("clrsr %0" : : "n"(c));
 

Enumerations

enum  qspi_io_sample_edge_t { qspi_io_sample_edge_rising = 0 , qspi_io_sample_edge_falling }
 
enum  qspi_io_source_clock_t { qspi_io_source_clock_ref = 0 , qspi_io_source_clock_xcore }
 
enum  qspi_io_transfer_mode_t { qspi_io_transfer_normal = 0 , qspi_io_transfer_nibble_swap }
 
enum  qspi_io_transaction_type_t { qspi_io_full_speed = 0 , qspi_io_spi_read }
 

Functions

uint32_t qspi_io_byte_to_mosi (uint32_t x)
 
uint32_t qspi_io_miso_to_byte (uint32_t x)
 
uint32_t qspi_io_nibble_swap (uint32_t word)
 
void qspi_io_start_transaction (qspi_io_ctx_t *ctx, uint32_t first_word, size_t len, qspi_io_transaction_type_t transaction_type)
 
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)
 
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)
 
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)
 
void qspi_io_sio_direction_input (qspi_io_ctx_t *ctx)
 
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)
 
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)
 
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)
 
void qspi_io_miso_poll (const qspi_io_ctx_t *ctx, const uint8_t mask, const uint8_t val, uint32_t start_time)
 
void qspi_io_end_transaction (const qspi_io_ctx_t *ctx)
 
void qspi_io_deinit (const qspi_io_ctx_t *ctx)
 
void qspi_io_init (const qspi_io_ctx_t *ctx, qspi_io_source_clock_t source_clock)
 

Detailed Description

The public API for using HIL QSPI I/O.

Macro Definition Documentation

◆ QSPI_IO_BYTE_TO_MOSI

#define QSPI_IO_BYTE_TO_MOSI (   x)
Value:
( \
((((x) >> 0) & 1) | 0xE) << (0 * 4) | \
((((x) >> 1) & 1) | 0xE) << (1 * 4) | \
((((x) >> 2) & 1) | 0xE) << (2 * 4) | \
((((x) >> 3) & 1) | 0xE) << (3 * 4) | \
((((x) >> 4) & 1) | 0xE) << (4 * 4) | \
((((x) >> 5) & 1) | 0xE) << (5 * 4) | \
((((x) >> 6) & 1) | 0xE) << (6 * 4) | \
((((x) >> 7) & 1) | 0xE) << (7 * 4) )

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
xThe byte to send out to MOSI.

Enumeration Type Documentation

◆ qspi_io_sample_edge_t

Enum type used to set which SCLK edge SIO is sampled on.

Enumerator
qspi_io_sample_edge_rising 

Sample SIO on the rising edge

qspi_io_sample_edge_falling 

Sample SIO on the falling edge

◆ qspi_io_source_clock_t

Enum type used to set which of the two clock sources SCLK is derived from.

Enumerator
qspi_io_source_clock_ref 

SCLK is derived from the 100 MHz reference clock

qspi_io_source_clock_xcore 

SCLK is derived from the core clock

◆ 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.

Enumerator
qspi_io_full_speed 

The transaction will be full speed with dummy cycles

qspi_io_spi_read 

The transaction will be low speed without dummy cycles

◆ qspi_io_transfer_mode_t

Enum type used to specify whether or not nibbles should be swapped during transfers.

Enumerator
qspi_io_transfer_normal 

Do not swap nibbles

qspi_io_transfer_nibble_swap 

Swap nibbles

Function Documentation

◆ qspi_io_byte_to_mosi()

uint32_t qspi_io_byte_to_mosi ( uint32_t  x)
inline

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
xThe byte to send out to MOSI.
Returns
the word to output to SIO.

◆ qspi_io_bytes_in()

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 
)
inline

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
ctxPointer to the QSPI I/O context.
transfer_modeCan 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.
dataPointer to the byte array to save the received data to. This MUST begin on a 4-byte boundary.
start_timeThe 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.
lenThe number of bytes to input.

◆ qspi_io_bytes_out()

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 
)
inline

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
ctxPointer to the QSPI I/O context.
transfer_modeCan 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.
dataPointer to the byte array to output. This MUST begin on a 4-byte boundary.
lenThe number of bytes in data to output.

◆ qspi_io_deinit()

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
ctxPointer to the QSPI I/O context. This should have been previously initialized with qspi_io_init().

◆ qspi_io_end_transaction()

void qspi_io_end_transaction ( const qspi_io_ctx_t ctx)
inline

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
ctxPointer to the QSPI I/O context.

◆ 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
ctxPointer to the QSPI I/O context. This must be initialized with the clock block and ports to use.
source_clockSet 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_miso_in()

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 
)
inline

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
ctxPointer to the QSPI I/O context.
transfer_modeCan 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.
dataPointer to the byte array to save the received data to.
start_timeThe 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.
lenThe number of words to input.

◆ qspi_io_miso_poll()

void qspi_io_miso_poll ( const qspi_io_ctx_t ctx,
const uint8_t  mask,
const uint8_t  val,
uint32_t  start_time 
)
inline

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
ctxPointer to the QSPI I/O context.
maskThe bitmask to apply to the received byte before comparing it to val;
valThe value that the received byte, masked with mask, must match before returning.
start_timeThe 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.

◆ qspi_io_miso_to_byte()

uint32_t qspi_io_miso_to_byte ( uint32_t  x)
inline

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
xThe word received on SIO.
Returns
the byte received on MISO.

◆ qspi_io_mosi_out()

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 
)
inline

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
ctxPointer to the QSPI I/O context.
transfer_modeCan 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.
dataPointer to the byte array to output.
lenThe number of words in data to output.

◆ qspi_io_nibble_swap()

uint32_t qspi_io_nibble_swap ( uint32_t  word)
inline

This function swaps the nibbles in each of the four bytes of word.

Parameters
wordThe word to nibble swap.
Returns
the nibble swapped word.

◆ qspi_io_sio_direction_input()

void qspi_io_sio_direction_input ( qspi_io_ctx_t ctx)
inline

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
ctxPointer to the QSPI I/O context.

◆ qspi_io_start_transaction()

void qspi_io_start_transaction ( qspi_io_ctx_t ctx,
uint32_t  first_word,
size_t  len,
qspi_io_transaction_type_t  transaction_type 
)
inline

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.
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
ctxPointer to the QSPI I/O context.
first_wordThe first word to output.
lenThe 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_typeSet 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.

◆ qspi_io_words_in()

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 
)
inline

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
ctxPointer to the QSPI I/O context.
transfer_modeCan 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.
dataPointer to the word array to save the received data to.
start_timeThe 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.
lenThe number of words to input.

◆ qspi_io_words_out()

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 
)
inline

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
ctxPointer to the QSPI I/O context.
transfer_modeCan 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.
dataPointer to the word array to output.
lenThe number of words in data to output.