ECSPI driver includes functional APIs and transactional APIs.
Functional APIs are feature/property target low level APIs. Functional APIs can be used for ECSPI initialization/configuration/operation for optimization/customization purpose. Using the functional API requires the knowledge of the SPI peripheral and how to organize functional APIs to meet the application requirements. All functional API use the peripheral base address as the first parameter. ECSPI functional operation groups provide the functional API set.
Transactional APIs are transaction target high level APIs. Transactional APIs can be used to enable the peripheral and in the application if the code size and performance of transactional APIs satisfy the requirements. If the code size and performance are a critical requirement, see the transactional API implementation and write a custom code. All transactional APIs use the spi_handle_t as the first parameter. Initialize the handle by calling the SPI_MasterTransferCreateHandle() or SPI_SlaveTransferCreateHandle() API.
Transactional APIs support asynchronous transfer. This means that the functions SPI_MasterTransferNonBlocking() and SPI_SlaveTransferNonBlocking() set up the interrupt for data transfer. When the transfer completes, the upper layer is notified through a callback function with the kStatus_SPI_Idle status.
Typical use case
SPI master transfer using polling method
Refer to the driver examples codes located at <SDK_ROOT>/boards/<BOARD>/driver_examples/ecspi
SPI master transfer using an interrupt method
Refer to the driver examples codes located at <SDK_ROOT>/boards/<BOARD>/driver_examples/ecspi
|
#define | ECSPI_DUMMYDATA (0xFFFFFFFFU) |
| ECSPI dummy transfer data, the data is sent while txBuff is NULL. More...
|
|
|
typedef ecspi_master_handle_t | ecspi_slave_handle_t |
| Slave handle is the same with master handle.
|
|
typedef void(* | ecspi_master_callback_t )(ECSPI_Type *base, ecspi_master_handle_t *handle, status_t status, void *userData) |
| ECSPI master callback for finished transmit.
|
|
typedef void(* | ecspi_slave_callback_t )(ECSPI_Type *base, ecspi_slave_handle_t *handle, status_t status, void *userData) |
| ECSPI slave callback for finished transmit.
|
|
|
enum | {
kStatus_ECSPI_Busy = MAKE_STATUS(kStatusGroup_ECSPI, 0),
kStatus_ECSPI_Idle = MAKE_STATUS(kStatusGroup_ECSPI, 1),
kStatus_ECSPI_Error = MAKE_STATUS(kStatusGroup_ECSPI, 2),
kStatus_ECSPI_HardwareOverFlow = MAKE_STATUS(kStatusGroup_ECSPI, 3)
} |
| Return status for the ECSPI driver. More...
|
|
enum | ecspi_clock_polarity_t {
kECSPI_PolarityActiveHigh = 0x0U,
kECSPI_PolarityActiveLow
} |
| ECSPI clock polarity configuration. More...
|
|
enum | ecspi_clock_phase_t {
kECSPI_ClockPhaseFirstEdge,
kECSPI_ClockPhaseSecondEdge
} |
| ECSPI clock phase configuration. More...
|
|
enum | {
kECSPI_TxfifoEmptyInterruptEnable = ECSPI_INTREG_TEEN_MASK,
kECSPI_TxFifoDataRequstInterruptEnable = ECSPI_INTREG_TDREN_MASK,
kECSPI_TxFifoFullInterruptEnable = ECSPI_INTREG_TFEN_MASK,
kECSPI_RxFifoReadyInterruptEnable = ECSPI_INTREG_RREN_MASK,
kECSPI_RxFifoDataRequstInterruptEnable = ECSPI_INTREG_RDREN_MASK,
kECSPI_RxFifoFullInterruptEnable = ECSPI_INTREG_RFEN_MASK,
kECSPI_RxFifoOverFlowInterruptEnable = ECSPI_INTREG_ROEN_MASK,
kECSPI_TransferCompleteInterruptEnable = ECSPI_INTREG_TCEN_MASK,
kECSPI_AllInterruptEnable
} |
| ECSPI interrupt sources. More...
|
|
enum | {
kECSPI_TxfifoEmptyFlag = ECSPI_STATREG_TE_MASK,
kECSPI_TxFifoDataRequstFlag = ECSPI_STATREG_TDR_MASK,
kECSPI_TxFifoFullFlag = ECSPI_STATREG_TF_MASK,
kECSPI_RxFifoReadyFlag = ECSPI_STATREG_RR_MASK,
kECSPI_RxFifoDataRequstFlag = ECSPI_STATREG_RDR_MASK,
kECSPI_RxFifoFullFlag = ECSPI_STATREG_RF_MASK,
kECSPI_RxFifoOverFlowFlag = ECSPI_STATREG_RO_MASK,
kECSPI_TransferCompleteFlag = ECSPI_STATREG_TC_MASK
} |
| ECSPI status flags. More...
|
|
enum | {
kECSPI_TxDmaEnable = ECSPI_DMAREG_TEDEN_MASK,
kECSPI_RxDmaEnable = ECSPI_DMAREG_RXDEN_MASK,
kECSPI_DmaAllEnable = (ECSPI_DMAREG_TEDEN_MASK | ECSPI_DMAREG_RXDEN_MASK)
} |
| ECSPI DMA enable. More...
|
|
enum | ecspi_Data_ready_t {
kECSPI_DataReadyIgnore = 0x0U,
kECSPI_DataReadyFallingEdge,
kECSPI_DataReadyLowLevel
} |
| ECSPI SPI_RDY signal configuration. More...
|
|
enum | ecspi_channel_source_t {
kECSPI_Channel0 = 0x0U,
kECSPI_Channel1,
kECSPI_Channel2,
kECSPI_Channel3
} |
| ECSPI channel select source. More...
|
|
enum | ecspi_master_slave_mode_t {
kECSPI_Slave = 0U,
kECSPI_Master
} |
| ECSPI master or slave mode configuration. More...
|
|
enum | ecspi_data_line_inactive_state_t {
kECSPI_DataLineInactiveStateHigh = 0x0U,
kECSPI_DataLineInactiveStateLow
} |
| ECSPI data line inactive state configuration. More...
|
|
enum | ecspi_clock_inactive_state_t {
kECSPI_ClockInactiveStateLow = 0x0U,
kECSPI_ClockInactiveStateHigh
} |
| ECSPI clock inactive state configuration. More...
|
|
enum | ecspi_chip_select_active_state_t {
kECSPI_ChipSelectActiveStateLow = 0x0U,
kECSPI_ChipSelectActiveStateHigh
} |
| ECSPI active state configuration. More...
|
|
enum | ecspi_wave_form_t {
kECSPI_WaveFormSingle = 0x0U,
kECSPI_WaveFormMultiple
} |
| ECSPI wave form configuration. More...
|
|
enum | ecspi_sample_period_clock_source_t {
kECSPI_spiClock = 0x0U,
kECSPI_lowFreqClock
} |
| ECSPI sample period clock configuration. More...
|
|
|
static void | ECSPI_EnableDMA (ECSPI_Type *base, uint32_t mask, bool enable) |
| Enables the DMA source for ECSPI. More...
|
|
|
void | ECSPI_MasterTransferCreateHandle (ECSPI_Type *base, ecspi_master_handle_t *handle, ecspi_master_callback_t callback, void *userData) |
| Initializes the ECSPI master handle. More...
|
|
status_t | ECSPI_MasterTransferBlocking (ECSPI_Type *base, ecspi_transfer_t *xfer) |
| Transfers a block of data using a polling method. More...
|
|
status_t | ECSPI_MasterTransferNonBlocking (ECSPI_Type *base, ecspi_master_handle_t *handle, ecspi_transfer_t *xfer) |
| Performs a non-blocking ECSPI interrupt transfer. More...
|
|
status_t | ECSPI_MasterTransferGetCount (ECSPI_Type *base, ecspi_master_handle_t *handle, size_t *count) |
| Gets the bytes of the ECSPI interrupt transferred. More...
|
|
void | ECSPI_MasterTransferAbort (ECSPI_Type *base, ecspi_master_handle_t *handle) |
| Aborts an ECSPI transfer using interrupt. More...
|
|
void | ECSPI_MasterTransferHandleIRQ (ECSPI_Type *base, ecspi_master_handle_t *handle) |
| Interrupts the handler for the ECSPI. More...
|
|
void | ECSPI_SlaveTransferCreateHandle (ECSPI_Type *base, ecspi_slave_handle_t *handle, ecspi_slave_callback_t callback, void *userData) |
| Initializes the ECSPI slave handle. More...
|
|
static status_t | ECSPI_SlaveTransferNonBlocking (ECSPI_Type *base, ecspi_slave_handle_t *handle, ecspi_transfer_t *xfer) |
| Performs a non-blocking ECSPI slave interrupt transfer. More...
|
|
static status_t | ECSPI_SlaveTransferGetCount (ECSPI_Type *base, ecspi_slave_handle_t *handle, size_t *count) |
| Gets the bytes of the ECSPI interrupt transferred. More...
|
|
static void | ECSPI_SlaveTransferAbort (ECSPI_Type *base, ecspi_slave_handle_t *handle) |
| Aborts an ECSPI slave transfer using interrupt. More...
|
|
void | ECSPI_SlaveTransferHandleIRQ (ECSPI_Type *base, ecspi_slave_handle_t *handle) |
| Interrupts a handler for the ECSPI slave. More...
|
|
struct ecspi_channel_config_t |
struct ecspi_master_config_t |
bool ecspi_master_config_t::enableLoopback |
struct ecspi_slave_config_t |
struct _ecspi_master_handle |
#define FSL_ECSPI_DRIVER_VERSION (MAKE_VERSION(2, 0, 2)) |
#define ECSPI_DUMMYDATA (0xFFFFFFFFU) |
Enumerator |
---|
kStatus_ECSPI_Busy |
ECSPI bus is busy.
|
kStatus_ECSPI_Idle |
ECSPI is idle.
|
kStatus_ECSPI_Error |
ECSPI error.
|
kStatus_ECSPI_HardwareOverFlow |
ECSPI hardware overflow.
|
Enumerator |
---|
kECSPI_PolarityActiveHigh |
Active-high ECSPI polarity high (idles low).
|
kECSPI_PolarityActiveLow |
Active-low ECSPI polarity low (idles high).
|
Enumerator |
---|
kECSPI_ClockPhaseFirstEdge |
First edge on SPSCK occurs at the middle of the first cycle of a data transfer.
|
kECSPI_ClockPhaseSecondEdge |
First edge on SPSCK occurs at the start of the first cycle of a data transfer.
|
Enumerator |
---|
kECSPI_TxfifoEmptyInterruptEnable |
Transmit FIFO buffer empty interrupt.
|
kECSPI_TxFifoDataRequstInterruptEnable |
Transmit FIFO data requst interrupt.
|
kECSPI_TxFifoFullInterruptEnable |
Transmit FIFO full interrupt.
|
kECSPI_RxFifoReadyInterruptEnable |
Receiver FIFO ready interrupt.
|
kECSPI_RxFifoDataRequstInterruptEnable |
Receiver FIFO data requst interrupt.
|
kECSPI_RxFifoFullInterruptEnable |
Receiver FIFO full interrupt.
|
kECSPI_RxFifoOverFlowInterruptEnable |
Receiver FIFO buffer overflow interrupt.
|
kECSPI_TransferCompleteInterruptEnable |
Transfer complete interrupt.
|
kECSPI_AllInterruptEnable |
All interrupt.
|
Enumerator |
---|
kECSPI_TxfifoEmptyFlag |
Transmit FIFO buffer empty flag.
|
kECSPI_TxFifoDataRequstFlag |
Transmit FIFO data requst flag.
|
kECSPI_TxFifoFullFlag |
Transmit FIFO full flag.
|
kECSPI_RxFifoReadyFlag |
Receiver FIFO ready flag.
|
kECSPI_RxFifoDataRequstFlag |
Receiver FIFO data requst flag.
|
kECSPI_RxFifoFullFlag |
Receiver FIFO full flag.
|
kECSPI_RxFifoOverFlowFlag |
Receiver FIFO buffer overflow flag.
|
kECSPI_TransferCompleteFlag |
Transfer complete flag.
|
Enumerator |
---|
kECSPI_TxDmaEnable |
Tx DMA request source.
|
kECSPI_RxDmaEnable |
Rx DMA request source.
|
kECSPI_DmaAllEnable |
All DMA request source.
|
Enumerator |
---|
kECSPI_DataReadyIgnore |
SPI_RDY signal is ignored.
|
kECSPI_DataReadyFallingEdge |
SPI_RDY signal will be triggerd by the falling edge.
|
kECSPI_DataReadyLowLevel |
SPI_RDY signal will be triggerd by a low level.
|
Enumerator |
---|
kECSPI_Channel0 |
Channel 0 is selectd.
|
kECSPI_Channel1 |
Channel 1 is selectd.
|
kECSPI_Channel2 |
Channel 2 is selectd.
|
kECSPI_Channel3 |
Channel 3 is selectd.
|
Enumerator |
---|
kECSPI_Slave |
ECSPI peripheral operates in slave mode.
|
kECSPI_Master |
ECSPI peripheral operates in master mode.
|
Enumerator |
---|
kECSPI_DataLineInactiveStateHigh |
The data line inactive state stays high.
|
kECSPI_DataLineInactiveStateLow |
The data line inactive state stays low.
|
Enumerator |
---|
kECSPI_ClockInactiveStateLow |
The SCLK inactive state stays low.
|
kECSPI_ClockInactiveStateHigh |
The SCLK inactive state stays high.
|
Enumerator |
---|
kECSPI_ChipSelectActiveStateLow |
The SS signal line active stays low.
|
kECSPI_ChipSelectActiveStateHigh |
The SS signal line active stays high.
|
Enumerator |
---|
kECSPI_WaveFormSingle |
The wave form for signal burst.
|
kECSPI_WaveFormMultiple |
The wave form for multiple burst.
|
Enumerator |
---|
kECSPI_spiClock |
The sample period clock source is SCLK.
|
kECSPI_lowFreqClock |
The sample seriod clock source is low_frequency reference clock(32.768 kHz).
|
uint32_t ECSPI_GetInstance |
( |
ECSPI_Type * |
base | ) |
|
The purpose of this API is to get the configuration structure initialized for use in ECSPI_MasterInit(). User may use the initialized structure unchanged in ECSPI_MasterInit, or modify some fields of the structure before calling ECSPI_MasterInit. After calling this API, the master is ready to transfer. Example:
- Parameters
-
config | pointer to config structure |
The configuration structure can be filled by user from scratch, or be set with default values by ECSPI_MasterGetDefaultConfig(). After calling this API, the slave is ready to transfer. Example
- Parameters
-
base | ECSPI base pointer |
config | pointer to master configuration structure |
srcClock_Hz | Source clock frequency. |
The purpose of this API is to get the configuration structure initialized for use in ECSPI_SlaveInit(). User may use the initialized structure unchanged in ECSPI_SlaveInit(), or modify some fields of the structure before calling ECSPI_SlaveInit(). After calling this API, the master is ready to transfer. Example:
ecspi_Slaveconfig_t config;
- Parameters
-
config | pointer to config structure |
The configuration structure can be filled by user from scratch, or be set with default values by ECSPI_SlaveGetDefaultConfig(). After calling this API, the slave is ready to transfer. Example
ecspi_Salveconfig_t config = {
...
};
- Parameters
-
base | ECSPI base pointer |
config | pointer to master configuration structure |
void ECSPI_Deinit |
( |
ECSPI_Type * |
base | ) |
|
Calling this API resets the ECSPI module, gates the ECSPI clock. The ECSPI module can't work unless calling the ECSPI_MasterInit/ECSPI_SlaveInit to initialize module.
- Parameters
-
static void ECSPI_Enable |
( |
ECSPI_Type * |
base, |
|
|
bool |
enable |
|
) |
| |
|
inlinestatic |
- Parameters
-
base | ECSPI base pointer |
enable | pass true to enable module, false to disable module |
static uint32_t ECSPI_GetStatusFlags |
( |
ECSPI_Type * |
base | ) |
|
|
inlinestatic |
- Parameters
-
- Returns
- ECSPI Status, use status flag to AND #_ecspi_flags could get the related status.
static void ECSPI_ClearStatusFlags |
( |
ECSPI_Type * |
base, |
|
|
uint32_t |
mask |
|
) |
| |
|
inlinestatic |
- Parameters
-
base | ECSPI base pointer |
mask | ECSPI Status, use status flag to AND #_ecspi_flags could get the related status. |
static void ECSPI_EnableInterrupts |
( |
ECSPI_Type * |
base, |
|
|
uint32_t |
mask |
|
) |
| |
|
inlinestatic |
- Parameters
-
base | ECSPI base pointer |
mask | ECSPI interrupt source. The parameter can be any combination of the following values:
- kECSPI_TxfifoEmptyInterruptEnable
- kECSPI_TxFifoDataRequstInterruptEnable
- kECSPI_TxFifoFullInterruptEnable
- kECSPI_RxFifoReadyInterruptEnable
- kECSPI_RxFifoDataRequstInterruptEnable
- kECSPI_RxFifoFullInterruptEnable
- kECSPI_RxFifoOverFlowInterruptEnable
- kECSPI_TransferCompleteInterruptEnable
- kECSPI_AllInterruptEnable
|
static void ECSPI_DisableInterrupts |
( |
ECSPI_Type * |
base, |
|
|
uint32_t |
mask |
|
) |
| |
|
inlinestatic |
- Parameters
-
base | ECSPI base pointer |
mask | ECSPI interrupt source. The parameter can be any combination of the following values:
- kECSPI_TxfifoEmptyInterruptEnable
- kECSPI_TxFifoDataRequstInterruptEnable
- kECSPI_TxFifoFullInterruptEnable
- kECSPI_RxFifoReadyInterruptEnable
- kECSPI_RxFifoDataRequstInterruptEnable
- kECSPI_RxFifoFullInterruptEnable
- kECSPI_RxFifoOverFlowInterruptEnable
- kECSPI_TransferCompleteInterruptEnable
- kECSPI_AllInterruptEnable
|
static void ECSPI_SoftwareReset |
( |
ECSPI_Type * |
base | ) |
|
|
inlinestatic |
- Parameters
-
base | ECSPI base pointer |
channel | ECSPI channel source |
- Returns
- mode of channel
static void ECSPI_EnableDMA |
( |
ECSPI_Type * |
base, |
|
|
uint32_t |
mask, |
|
|
bool |
enable |
|
) |
| |
|
inlinestatic |
- Parameters
-
base | ECSPI base pointer |
source | ECSPI DMA source. |
enable | True means enable DMA, false means disable DMA |
static uint8_t ECSPI_GetTxFifoCount |
( |
ECSPI_Type * |
base | ) |
|
|
inlinestatic |
- Parameters
-
- Returns
- the number of words in Tx FIFO buffer.
static uint8_t ECSPI_GetRxFifoCount |
( |
ECSPI_Type * |
base | ) |
|
|
inlinestatic |
- Parameters
-
- Returns
- the number of words in Rx FIFO buffer.
- Parameters
-
base | ECSPI base pointer |
channel | Channel source. |
The purpose of this API is to set the channel will be use to transfer. User may use this API after instance has been initialized or before transfer start. The configuration structure #_ecspi_channel_config_ can be filled by user from scratch. After calling this API, user can select this channel as transfer channel.
- Parameters
-
base | ECSPI base pointer |
channel | Channel source. |
config | Configuration struct of channel |
void ECSPI_SetBaudRate |
( |
ECSPI_Type * |
base, |
|
|
uint32_t |
baudRate_Bps, |
|
|
uint32_t |
srcClock_Hz |
|
) |
| |
This is only used in master.
- Parameters
-
base | ECSPI base pointer |
baudRate_Bps | baud rate needed in Hz. |
srcClock_Hz | ECSPI source clock frequency in Hz. |
void ECSPI_WriteBlocking |
( |
ECSPI_Type * |
base, |
|
|
uint32_t * |
buffer, |
|
|
size_t |
size |
|
) |
| |
- Note
- This function blocks via polling until all bytes have been sent.
- Parameters
-
base | ECSPI base pointer |
buffer | The data bytes to send |
size | The number of data bytes to send |
static void ECSPI_WriteData |
( |
ECSPI_Type * |
base, |
|
|
uint32_t |
data |
|
) |
| |
|
inlinestatic |
- Parameters
-
base | ECSPI base pointer |
data | Data needs to be write. |
static uint32_t ECSPI_ReadData |
( |
ECSPI_Type * |
base | ) |
|
|
inlinestatic |
- Parameters
-
- Returns
- Data in the register.
void ECSPI_MasterTransferCreateHandle |
( |
ECSPI_Type * |
base, |
|
|
ecspi_master_handle_t * |
handle, |
|
|
ecspi_master_callback_t |
callback, |
|
|
void * |
userData |
|
) |
| |
This function initializes the ECSPI master handle which can be used for other ECSPI master transactional APIs. Usually, for a specified ECSPI instance, call this API once to get the initialized handle.
- Parameters
-
base | ECSPI peripheral base address. |
handle | ECSPI handle pointer. |
callback | Callback function. |
userData | User data. |
status_t ECSPI_MasterTransferBlocking |
( |
ECSPI_Type * |
base, |
|
|
ecspi_transfer_t * |
xfer |
|
) |
| |
- Parameters
-
base | SPI base pointer |
xfer | pointer to spi_xfer_config_t structure |
- Return values
-
kStatus_Success | Successfully start a transfer. |
kStatus_InvalidArgument | Input argument is invalid. |
status_t ECSPI_MasterTransferNonBlocking |
( |
ECSPI_Type * |
base, |
|
|
ecspi_master_handle_t * |
handle, |
|
|
ecspi_transfer_t * |
xfer |
|
) |
| |
- Note
- The API immediately returns after transfer initialization is finished.
-
If ECSPI transfer data frame size is 16 bits, the transfer size cannot be an odd number.
- Parameters
-
base | ECSPI peripheral base address. |
handle | pointer to ecspi_master_handle_t structure which stores the transfer state |
xfer | pointer to ecspi_transfer_t structure |
- Return values
-
kStatus_Success | Successfully start a transfer. |
kStatus_InvalidArgument | Input argument is invalid. |
kStatus_ECSPI_Busy | ECSPI is not idle, is running another transfer. |
status_t ECSPI_MasterTransferGetCount |
( |
ECSPI_Type * |
base, |
|
|
ecspi_master_handle_t * |
handle, |
|
|
size_t * |
count |
|
) |
| |
- Parameters
-
base | ECSPI peripheral base address. |
handle | Pointer to ECSPI transfer handle, this should be a static variable. |
count | Transferred bytes of ECSPI master. |
- Return values
-
kStatus_ECSPI_Success | Succeed get the transfer count. |
kStatus_NoTransferInProgress | There is not a non-blocking transaction currently in progress. |
void ECSPI_MasterTransferAbort |
( |
ECSPI_Type * |
base, |
|
|
ecspi_master_handle_t * |
handle |
|
) |
| |
- Parameters
-
base | ECSPI peripheral base address. |
handle | Pointer to ECSPI transfer handle, this should be a static variable. |
void ECSPI_MasterTransferHandleIRQ |
( |
ECSPI_Type * |
base, |
|
|
ecspi_master_handle_t * |
handle |
|
) |
| |
- Parameters
-
base | ECSPI peripheral base address. |
handle | pointer to ecspi_master_handle_t structure which stores the transfer state. |
This function initializes the ECSPI slave handle which can be used for other ECSPI slave transactional APIs. Usually, for a specified ECSPI instance, call this API once to get the initialized handle.
- Parameters
-
base | ECSPI peripheral base address. |
handle | ECSPI handle pointer. |
callback | Callback function. |
userData | User data. |
- Note
- The API returns immediately after the transfer initialization is finished.
- Parameters
-
base | ECSPI peripheral base address. |
handle | pointer to ecspi_master_handle_t structure which stores the transfer state |
xfer | pointer to ecspi_transfer_t structure |
- Return values
-
kStatus_Success | Successfully start a transfer. |
kStatus_InvalidArgument | Input argument is invalid. |
kStatus_ECSPI_Busy | ECSPI is not idle, is running another transfer. |
static status_t ECSPI_SlaveTransferGetCount |
( |
ECSPI_Type * |
base, |
|
|
ecspi_slave_handle_t * |
handle, |
|
|
size_t * |
count |
|
) |
| |
|
inlinestatic |
- Parameters
-
base | ECSPI peripheral base address. |
handle | Pointer to ECSPI transfer handle, this should be a static variable. |
count | Transferred bytes of ECSPI slave. |
- Return values
-
kStatus_ECSPI_Success | Succeed get the transfer count. |
kStatus_NoTransferInProgress | There is not a non-blocking transaction currently in progress. |
- Parameters
-
base | ECSPI peripheral base address. |
handle | Pointer to ECSPI transfer handle, this should be a static variable. |
- Parameters
-
base | ECSPI peripheral base address. |
handle | pointer to ecspi_slave_handle_t structure which stores the transfer state |