/** *@brief Function for handling Tx procedure. */ static void ser_phy_uart_tx(void) { if (mp_tx_stream != NULL) { bool tx_done_flag = false; /**< Local flag for indicating that TX is completed */ uint32_t err_code = NRF_SUCCESS; /**< Error code for storing result of app_uart_put */ //Blocking TXRDY interrupt is done to avoid interrupting when this procedure is //triggered from main context NRF_UART0->INTENCLR = (UART_INTENSET_TXDRDY_Set << UART_INTENSET_TXDRDY_Pos); //Notify upper layer if whole packet has been transmitted if (m_tx_stream_index == m_tx_stream_length) { callback_packet_sent(); tx_done_flag = true; } //First transmit 2 bytes of packet length else if (m_tx_stream_index < SER_PHY_HEADER_SIZE) { err_code = app_uart_put(m_tx_length_buf[m_tx_stream_index]); } //Then transmit payload else if (m_tx_stream_index < m_tx_stream_length) { err_code = app_uart_put(mp_tx_stream[m_tx_stream_index - SER_PHY_HEADER_SIZE]); } //Increment index only if byte was sent without errors if ((err_code == NRF_SUCCESS) && !tx_done_flag) { m_tx_stream_index++; } //Unblock TXRDY interrupts NRF_UART0->INTENSET = (UART_INTENSET_TXDRDY_Set << UART_INTENSET_TXDRDY_Pos); } }
/** * \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; } }