/** * \brief Slave driver main state machine * For UML graph, please refer to SDK documentation */ static void spi_slave_event_handle(spi_slave_evt_t event) { static uint32_t err_code = NRF_SUCCESS; static uint16_t packetLength; switch (m_trans_state) { case SPI_RAW_STATE_SETUP_HEADER: m_trans_state = SPI_RAW_STATE_RX_HEADER; err_code = header_get(); break; case SPI_RAW_STATE_RX_HEADER: if (event.evt_type == SPI_SLAVE_BUFFERS_SET_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_BUFFERS_SET(0); set_ready_line(); } if (event.evt_type == SPI_SLAVE_XFER_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_RX_XFER_DONE(event.rx_amount); spi_slave_raw_assert(event.rx_amount == SER_PHY_HEADER_SIZE); packetLength = uint16_decode(m_header_rx_buffer); if (packetLength != 0 ) { m_trans_state = SPI_RAW_STATE_MEM_REQUESTED; m_buffer_reqested_flag = true; m_rx_packet_length = packetLength; callback_memory_request(packetLength); } else { if (m_p_tx_buffer) { clear_request_line(); m_trans_state = SPI_RAW_STATE_TX_HEADER; err_code = header_send(m_tx_packet_length); } else { //there is nothing to send - zero response facilitates pooling - but perhaps, it should be assert err_code = header_send(0); } } } break; case SPI_RAW_STATE_MEM_REQUESTED: if (event.evt_type == SPI_SLAVE_EVT_TYPE_MAX) //This is API dummy event { m_buffer_reqested_flag = false; m_trans_state = SPI_RAW_STATE_RX_PAYLOAD; m_accumulated_rx_packet_length = 0; err_code = frame_get(); } break; case SPI_RAW_STATE_RX_PAYLOAD: if (event.evt_type == SPI_SLAVE_BUFFERS_SET_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_BUFFERS_SET(0); set_ready_line(); } if (event.evt_type == SPI_SLAVE_XFER_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_RX_XFER_DONE(event.rx_amount); spi_slave_raw_assert(event.rx_amount == m_current_rx_frame_length); m_accumulated_rx_packet_length += m_current_rx_frame_length; if (m_accumulated_rx_packet_length < m_rx_packet_length ) { err_code = frame_get(); } else { spi_slave_raw_assert(m_accumulated_rx_packet_length == m_rx_packet_length); m_trans_state = SPI_RAW_STATE_RX_HEADER; err_code = header_get(); if (!m_trash_payload_flag) { callback_packet_received(m_p_rx_buffer, m_accumulated_rx_packet_length); } else { callback_packet_dropped(); } } } break; case SPI_RAW_STATE_TX_HEADER: if (event.evt_type == SPI_SLAVE_BUFFERS_SET_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_BUFFERS_SET(0); set_ready_line(); } if (event.evt_type == SPI_SLAVE_XFER_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_TX_XFER_DONE(event.tx_amount); spi_slave_raw_assert(event.tx_amount == SER_PHY_HEADER_SIZE + 1); m_trans_state = SPI_RAW_STATE_TX_PAYLOAD; m_accumulated_tx_packet_length = 0; err_code = frame_send(); } break; case SPI_RAW_STATE_TX_PAYLOAD: if (event.evt_type == SPI_SLAVE_BUFFERS_SET_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_BUFFERS_SET(0); set_ready_line(); } if (event.evt_type == SPI_SLAVE_XFER_DONE) { DEBUG_EVT_SPI_SLAVE_RAW_TX_XFER_DONE(event.tx_amount); spi_slave_raw_assert(event.tx_amount == m_current_tx_frame_length + 1); m_accumulated_tx_packet_length += m_current_tx_frame_length; if ( m_accumulated_tx_packet_length < m_tx_packet_length ) { err_code = frame_send(); } else { spi_slave_raw_assert(m_accumulated_tx_packet_length == m_tx_packet_length); //clear pointer before callback m_p_tx_buffer = NULL; callback_packet_transmitted(); //spi slave TX transfer is possible only when RX is ready, so return to waiting for a header m_trans_state = SPI_RAW_STATE_RX_HEADER; err_code = header_get(); } } break; default: err_code = NRF_ERROR_INVALID_STATE; break; } APP_ERROR_CHECK(err_code); }
/** * \brief Master driver main state machine * Executed only in the context of PendSV_Handler() * For UML graph, please refer to SDK documentation */ static void ser_phy_switch_state(ser_phy_event_source_t evt_src) { uint32_t err_code = NRF_SUCCESS; static bool m_wait_for_ready_flag = false; //local scheduling flag to defer RDY events switch (m_spi_master_state) { case SER_PHY_STATE_IDLE: if (evt_src == SER_PHY_EVT_GPIO_REQ) { m_wait_for_ready_flag = false; if (m_slave_ready_flag) { m_spi_master_state = SER_PHY_STATE_TX_ZERO_HEADER; err_code = header_send(0); } else { m_spi_master_state = SER_PHY_STATE_RX_WAIT_FOR_RDY; } } else if (evt_src == SER_PHY_EVT_TX_API_CALL) { spi_master_raw_assert(mp_tx_buffer != NULL); //api event with tx_buffer == NULL has no sense m_wait_for_ready_flag = false; if (m_slave_ready_flag) { m_spi_master_state = SER_PHY_STATE_TX_HEADER; err_code = header_send(m_tx_buf_len); } else { m_spi_master_state = SER_PHY_STATE_TX_WAIT_FOR_RDY; } } break; case SER_PHY_STATE_TX_WAIT_FOR_RDY: if (evt_src == SER_PHY_EVT_GPIO_RDY) { m_spi_master_state = SER_PHY_STATE_TX_HEADER; err_code = header_send(m_tx_buf_len); } break; case SER_PHY_STATE_RX_WAIT_FOR_RDY: if (evt_src == SER_PHY_EVT_GPIO_RDY) { m_spi_master_state = SER_PHY_STATE_TX_ZERO_HEADER; err_code = header_send(0); } break; case SER_PHY_STATE_TX_HEADER: if (evt_src == SER_PHY_EVT_SPI_TRANSFER_DONE) { m_tx_packet_length = m_tx_buf_len; m_accumulated_tx_packet_length = 0; if (m_slave_ready_flag) { m_spi_master_state = SER_PHY_STATE_TX_PAYLOAD; err_code = frame_send(); } else { m_wait_for_ready_flag = true; } } else if ((evt_src == SER_PHY_EVT_GPIO_RDY) && m_wait_for_ready_flag) { m_wait_for_ready_flag = false; m_spi_master_state = SER_PHY_STATE_TX_PAYLOAD; err_code = frame_send(); } break; case SER_PHY_STATE_TX_PAYLOAD: if (evt_src == SER_PHY_EVT_SPI_TRANSFER_DONE) { if (m_accumulated_tx_packet_length < m_tx_packet_length) { if (m_slave_ready_flag) { err_code = frame_send(); } else { m_wait_for_ready_flag = true; } } else { spi_master_raw_assert(m_accumulated_tx_packet_length == m_tx_packet_length); buffer_release(&mp_tx_buffer, &m_tx_buf_len); callback_packet_sent(); if ( m_slave_request_flag) { if (m_slave_ready_flag) { m_spi_master_state = SER_PHY_STATE_TX_ZERO_HEADER; err_code = header_send(0); } else { m_spi_master_state = SER_PHY_STATE_RX_WAIT_FOR_RDY; } } else { m_spi_master_state = SER_PHY_STATE_IDLE; //m_Tx_buffer is NULL - have to wait for API event } } } else if ((evt_src == SER_PHY_EVT_GPIO_RDY) && m_wait_for_ready_flag ) { m_wait_for_ready_flag = false; err_code = frame_send(); } break; case SER_PHY_STATE_TX_ZERO_HEADER: if (evt_src == SER_PHY_EVT_SPI_TRANSFER_DONE) { if (m_slave_ready_flag) { m_spi_master_state = SER_PHY_STATE_RX_HEADER; err_code = header_get(); } else { m_wait_for_ready_flag = true; } } else if ( (evt_src == SER_PHY_EVT_GPIO_RDY) && m_wait_for_ready_flag) { m_wait_for_ready_flag = false; m_spi_master_state = SER_PHY_STATE_RX_HEADER; err_code = header_get(); } break; case SER_PHY_STATE_RX_HEADER: if (evt_src == SER_PHY_EVT_SPI_TRANSFER_DONE) { m_spi_master_state = SER_PHY_STATE_MEMORY_REQUEST; m_rx_buf_len = uint16_decode(m_header_buffer); m_rx_packet_length = m_rx_buf_len; callback_mem_request(); } break; case SER_PHY_STATE_MEMORY_REQUEST: if (evt_src == SER_PHY_EVT_RX_API_CALL) { m_accumulated_rx_packet_length = 0; if (m_slave_ready_flag) { m_spi_master_state = SER_PHY_STATE_RX_PAYLOAD; err_code = frame_get(); } else { m_wait_for_ready_flag = true; } } else if ((evt_src == SER_PHY_EVT_GPIO_RDY) && m_wait_for_ready_flag) { m_wait_for_ready_flag = false; m_spi_master_state = SER_PHY_STATE_RX_PAYLOAD; err_code = frame_get(); } break; case SER_PHY_STATE_RX_PAYLOAD: if (evt_src == SER_PHY_EVT_SPI_TRANSFER_DONE) { m_accumulated_rx_packet_length += m_current_rx_packet_length; if (m_accumulated_rx_packet_length < m_rx_packet_length) { if (m_slave_ready_flag) { err_code = frame_get(); } else { m_wait_for_ready_flag = true; } } else { spi_master_raw_assert(m_accumulated_rx_packet_length == m_rx_packet_length); if (mp_rx_buffer == NULL) { callback_packet_dropped(); } else { callback_packet_received(); } buffer_release(&mp_rx_buffer, &m_rx_buf_len); if (mp_tx_buffer != NULL) //mp_tx_buffer !=NULL, this means that API_EVT was scheduled { if (m_slave_ready_flag ) { err_code = header_send(m_tx_buf_len); m_spi_master_state = SER_PHY_STATE_TX_HEADER; } else { m_spi_master_state = SER_PHY_STATE_TX_WAIT_FOR_RDY; } } else if (m_slave_request_flag) { if (m_slave_ready_flag) { m_spi_master_state = SER_PHY_STATE_TX_ZERO_HEADER; err_code = header_send(0); } else { m_spi_master_state = SER_PHY_STATE_RX_WAIT_FOR_RDY; } } else { m_spi_master_state = SER_PHY_STATE_IDLE; } } } else if ( evt_src == SER_PHY_EVT_GPIO_RDY && m_wait_for_ready_flag) { m_wait_for_ready_flag = false; err_code = frame_get(); } break; default: break; } if (err_code != NRF_SUCCESS) { (void)err_code; } }