aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/components/serialization/common/transport/ser_phy/ser_phy_spi_master.c
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/serialization/common/transport/ser_phy/ser_phy_spi_master.c')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/serialization/common/transport/ser_phy/ser_phy_spi_master.c804
1 files changed, 804 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/serialization/common/transport/ser_phy/ser_phy_spi_master.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/serialization/common/transport/ser_phy/ser_phy_spi_master.c
new file mode 100644
index 0000000..6065446
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/serialization/common/transport/ser_phy/ser_phy_spi_master.c
@@ -0,0 +1,804 @@
+/**
+ * Copyright (c) 2014 - 2018, Nordic Semiconductor ASA
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form, except as embedded into a Nordic
+ * Semiconductor ASA integrated circuit in a product or a software update for
+ * such product, must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * 4. This software, with or without modification, must only be used with a
+ * Nordic Semiconductor ASA integrated circuit.
+ *
+ * 5. Any software provided in binary form under this license must not be reverse
+ * engineered, decompiled, modified and/or disassembled.
+ *
+ * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
+ * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
+ * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+/**@file
+ *
+ * @defgroup ser_phy_spi_phy_driver_master ser_phy_nrf51_spi_master.c
+ * @{
+ * @ingroup ser_phy_spi_phy_driver_master
+ *
+ * @brief SPI_RAW PHY master driver.
+ */
+
+#include <stdio.h>
+#include "nrf_drv_gpiote.h"
+#include "nrf_drv_spi.h"
+#include "ser_phy.h"
+#include "ser_config.h"
+#include "app_util.h"
+#include "app_util_platform.h"
+#include "app_error.h"
+#include "nrf_error.h"
+#include "nrf_gpio.h"
+#include "nrf_gpiote.h"
+#include "boards.h"
+#include "app_error.h"
+#include "ser_phy_config_app.h"
+#include "ser_phy_debug_app.h"
+
+#define notUSE_PendSV
+
+#ifdef USE_PendSV
+
+#define SW_IRQn PendSV_IRQn
+#define SW_IRQ_Handler() PendSV_Handler()
+#define SET_Pend_SW_IRQ() SCB->ICSR = SCB->ICSR | SCB_ICSR_PENDSVSET_Msk //NVIC_SetPendingIRQ(PendSV_IRQn) - PendSV_IRQn is a negative - does not work with CMSIS
+
+#else
+
+#define SW_IRQn SWI3_IRQn
+#define SW_IRQ_Handler() SWI3_IRQHandler()
+#define SET_Pend_SW_IRQ() NVIC_SetPendingIRQ(SWI3_IRQn)
+#endif /* USE_PendSV */
+
+typedef enum
+{
+ SER_PHY_STATE_IDLE = 0,
+ SER_PHY_STATE_TX_HEADER,
+ SER_PHY_STATE_TX_WAIT_FOR_RDY,
+ SER_PHY_STATE_TX_PAYLOAD,
+ SER_PHY_STATE_RX_WAIT_FOR_RDY,
+ SER_PHY_STATE_TX_ZERO_HEADER,
+ SER_PHY_STATE_RX_HEADER,
+ SER_PHY_STATE_MEMORY_REQUEST,
+ SER_PHY_STATE_RX_PAYLOAD,
+ SER_PHY_STATE_DISABLED
+} ser_phy_spi_master_state_t;
+
+typedef enum
+{
+ SER_PHY_EVT_GPIO_RDY = 0,
+ SER_PHY_EVT_GPIO_REQ,
+ SER_PHY_EVT_SPI_TRANSFER_DONE,
+ SER_PHY_EVT_TX_API_CALL,
+ SER_PHY_EVT_RX_API_CALL
+} ser_phy_event_source_t;
+
+#define _static static
+
+_static uint8_t * mp_tx_buffer = NULL;
+_static uint16_t m_tx_buf_len = 0;
+
+_static uint8_t * mp_rx_buffer = NULL;
+_static uint16_t m_rx_buf_len = 0;
+_static uint8_t m_frame_buffer[SER_PHY_SPI_MTU_SIZE];
+_static uint8_t m_header_buffer[SER_PHY_HEADER_SIZE] = { 0 };
+
+_static uint16_t m_tx_packet_length = 0;
+_static uint16_t m_accumulated_tx_packet_length = 0;
+_static uint16_t m_current_tx_packet_length = 0;
+
+_static uint16_t m_rx_packet_length = 0;
+_static uint16_t m_accumulated_rx_packet_length = 0;
+_static uint16_t m_current_rx_packet_length = 0;
+
+_static volatile bool m_pend_req_flag = 0;
+_static volatile bool m_pend_rdy_flag = 0;
+_static volatile bool m_pend_xfer_flag = 0;
+_static volatile bool m_pend_rx_api_flag = 0;
+_static volatile bool m_pend_tx_api_flag = 0;
+
+_static volatile bool m_slave_ready_flag = false;
+_static volatile bool m_slave_request_flag = false;
+
+_static ser_phy_events_handler_t m_callback_events_handler = NULL;
+_static ser_phy_spi_master_state_t m_spi_master_state = SER_PHY_STATE_DISABLED;
+
+_static const nrf_drv_spi_t m_spi_master = SER_PHY_SPI_MASTER_INSTANCE;
+
+static void ser_phy_switch_state(ser_phy_event_source_t evt_src);
+
+static void spi_master_raw_assert(bool cond)
+{
+ APP_ERROR_CHECK_BOOL(cond);
+}
+
+void SW_IRQ_Handler()
+{
+ if (m_pend_req_flag)
+ {
+ m_pend_req_flag = false;
+ DEBUG_EVT_SPI_MASTER_RAW_REQUEST(0);
+ ser_phy_switch_state(SER_PHY_EVT_GPIO_REQ);
+ }
+
+ if (m_pend_rdy_flag)
+ {
+ m_pend_rdy_flag = false;
+ DEBUG_EVT_SPI_MASTER_RAW_READY(0);
+ ser_phy_switch_state(SER_PHY_EVT_GPIO_RDY);
+ }
+
+ if (m_pend_xfer_flag)
+ {
+ m_pend_xfer_flag = false;
+ DEBUG_EVT_SPI_MASTER_RAW_XFER_DONE(0);
+ ser_phy_switch_state(SER_PHY_EVT_SPI_TRANSFER_DONE);
+ }
+
+ if (m_pend_rx_api_flag)
+ {
+ m_pend_rx_api_flag = false;
+ DEBUG_EVT_SPI_MASTER_RAW_API_CALL(0);
+ ser_phy_switch_state(SER_PHY_EVT_RX_API_CALL);
+ }
+
+ if (m_pend_tx_api_flag)
+ {
+ m_pend_tx_api_flag = false;
+ DEBUG_EVT_SPI_MASTER_RAW_API_CALL(0);
+ ser_phy_switch_state(SER_PHY_EVT_TX_API_CALL);
+ }
+}
+
+static void ser_phy_spi_master_ready(nrf_drv_gpiote_pin_t pin,
+ nrf_gpiote_polarity_t action)
+{
+ if (nrf_gpio_pin_read(pin) == 0)
+ {
+ m_slave_ready_flag = true;
+ m_pend_rdy_flag = true;
+ }
+ else
+ {
+ m_slave_ready_flag = false;
+ }
+
+ DEBUG_EVT_SPI_MASTER_RAW_READY_EDGE((uint32_t) !m_slave_ready_flag);
+ SET_Pend_SW_IRQ();
+}
+
+static void ser_phy_spi_master_request(nrf_drv_gpiote_pin_t pin,
+ nrf_gpiote_polarity_t action)
+{
+ if (nrf_gpio_pin_read(pin) == 0)
+ {
+ m_slave_request_flag = true;
+ m_pend_req_flag = true;
+ }
+ else
+ {
+ m_slave_request_flag = false;
+ }
+
+ DEBUG_EVT_SPI_MASTER_RAW_REQUEST_EDGE((uint32_t) !m_slave_request_flag);
+ SET_Pend_SW_IRQ();
+}
+
+/* Send event SER_PHY_EVT_TX_PKT_SENT */
+static __INLINE void callback_packet_sent()
+{
+ ser_phy_evt_t event;
+
+ DEBUG_EVT_SPI_MASTER_PHY_TX_PKT_SENT(0);
+
+ event.evt_type = SER_PHY_EVT_TX_PKT_SENT;
+ m_callback_events_handler(event);
+}
+
+/* Send event SER_PHY_EVT_RX_PKT_DROPPED */
+static __INLINE void callback_packet_dropped()
+{
+ ser_phy_evt_t event;
+
+ DEBUG_EVT_SPI_MASTER_PHY_RX_PKT_DROPPED(0);
+
+ event.evt_type = SER_PHY_EVT_RX_PKT_DROPPED;
+ m_callback_events_handler(event);
+}
+
+/* Send event SER_PHY_EVT_RX_PKT_RECEIVED */
+static __INLINE void callback_packet_received()
+{
+ ser_phy_evt_t event;
+
+ DEBUG_EVT_SPI_MASTER_PHY_RX_PKT_RECEIVED(0);
+
+ event.evt_type = SER_PHY_EVT_RX_PKT_RECEIVED;
+ event.evt_params.rx_pkt_received.p_buffer = mp_rx_buffer;
+ event.evt_params.rx_pkt_received.num_of_bytes = m_rx_buf_len;
+ m_callback_events_handler(event);
+}
+
+/* Send event SER_PHY_EVT_RX_BUF_REQUEST */
+static __INLINE void callback_mem_request()
+{
+ ser_phy_evt_t event;
+
+ DEBUG_EVT_SPI_MASTER_PHY_BUF_REQUEST(0);
+
+ event.evt_type = SER_PHY_EVT_RX_BUF_REQUEST;
+ event.evt_params.rx_buf_request.num_of_bytes = m_rx_buf_len;
+ m_callback_events_handler(event);
+}
+
+/* Release buffer */
+static __INLINE void buffer_release(uint8_t * * const pp_buffer,
+ uint16_t * const p_buf_len)
+{
+ *pp_buffer = NULL;
+ *p_buf_len = 0;
+}
+
+/* Function computes current packet length */
+static uint16_t compute_current_packet_length(const uint16_t packet_length,
+ const uint16_t accumulated_packet_length)
+{
+ uint16_t current_packet_length = packet_length - accumulated_packet_length;
+
+ if (current_packet_length > SER_PHY_SPI_MTU_SIZE)
+ {
+ current_packet_length = SER_PHY_SPI_MTU_SIZE;
+ }
+
+ return current_packet_length;
+}
+
+static __INLINE uint32_t header_send(const uint16_t length)
+{
+ uint8_t buf_len_size = uint16_encode(length, m_header_buffer);
+
+ return nrf_drv_spi_transfer(&m_spi_master, m_header_buffer, buf_len_size, NULL, 0);
+}
+
+
+static __INLINE uint32_t frame_send()
+{
+ uint32_t err_code;
+
+ m_current_tx_packet_length = compute_current_packet_length(m_tx_packet_length,
+ m_accumulated_tx_packet_length);
+ err_code =
+ nrf_drv_spi_transfer(&m_spi_master,
+ &mp_tx_buffer[m_accumulated_tx_packet_length],
+ m_current_tx_packet_length,
+ NULL,
+ 0);
+ m_accumulated_tx_packet_length += m_current_tx_packet_length;
+ return err_code;
+}
+
+static __INLINE uint32_t header_get()
+{
+ return nrf_drv_spi_transfer(&m_spi_master, NULL, 0, m_header_buffer, SER_PHY_HEADER_SIZE);
+}
+
+static __INLINE uint32_t frame_get()
+{
+ uint32_t err_code;
+
+ m_current_rx_packet_length = compute_current_packet_length(m_rx_packet_length,
+ m_accumulated_rx_packet_length);
+
+ if (mp_rx_buffer)
+ {
+ err_code = nrf_drv_spi_transfer(&m_spi_master,
+ NULL,
+ 0,
+ &(mp_rx_buffer[m_accumulated_rx_packet_length]),
+ m_current_rx_packet_length);
+ }
+ else
+ {
+ err_code = nrf_drv_spi_transfer(&m_spi_master,
+ NULL,
+ 0,
+ m_frame_buffer,
+ m_current_rx_packet_length);
+ }
+ return 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;
+ }
+}
+
+static void ser_phy_spi_master_event_handler(nrf_drv_spi_evt_t const * p_event,
+ void * p_context)
+{
+ switch (p_event->type)
+ {
+ case NRF_DRV_SPI_EVENT_DONE:
+
+ /* Switch state */
+ m_pend_xfer_flag = true;
+ SET_Pend_SW_IRQ();
+
+ break;
+
+ default:
+ break;
+ }
+}
+
+static void ser_phy_init_PendSV(void)
+{
+ NVIC_SetPriority(SW_IRQn, APP_IRQ_PRIORITY_MID);
+ NVIC_EnableIRQ(SW_IRQn);
+}
+
+static ret_code_t ser_phy_init_gpiote(void)
+{
+ if (!nrf_drv_gpiote_is_init())
+ {
+ (void)nrf_drv_gpiote_init();
+ }
+ NVIC_SetPriority(GPIOTE_IRQn, APP_IRQ_PRIORITY_HIGH);
+
+ nrf_drv_gpiote_in_config_t config = GPIOTE_CONFIG_IN_SENSE_TOGGLE(true);
+ /* Enable pullup to ensure high state while connectivity device is reset */
+ config.pull = NRF_GPIO_PIN_PULLUP;
+ ret_code_t err_code = nrf_drv_gpiote_in_init(SER_PHY_SPI_MASTER_PIN_SLAVE_REQUEST,
+ &config, ser_phy_spi_master_request);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ nrf_drv_gpiote_in_event_enable(SER_PHY_SPI_MASTER_PIN_SLAVE_REQUEST,true);
+
+ err_code = nrf_drv_gpiote_in_init(SER_PHY_SPI_MASTER_PIN_SLAVE_READY,
+ &config, ser_phy_spi_master_ready);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+ nrf_drv_gpiote_in_event_enable(SER_PHY_SPI_MASTER_PIN_SLAVE_READY,true);
+
+ m_slave_request_flag = !(nrf_gpio_pin_read(SER_PHY_SPI_MASTER_PIN_SLAVE_REQUEST));
+ m_slave_ready_flag = !(nrf_gpio_pin_read(SER_PHY_SPI_MASTER_PIN_SLAVE_READY));
+
+ NVIC_ClearPendingIRQ(SW_IRQn);
+
+ return NRF_SUCCESS;
+}
+
+static void ser_phy_deinit_gpiote(void)
+{
+ nrf_drv_gpiote_in_uninit(SER_PHY_SPI_MASTER_PIN_SLAVE_REQUEST);
+ nrf_drv_gpiote_in_uninit(SER_PHY_SPI_MASTER_PIN_SLAVE_READY);
+}
+
+/* ser_phy API function */
+uint32_t ser_phy_tx_pkt_send(const uint8_t * p_buffer, uint16_t num_of_bytes)
+{
+ if (p_buffer == NULL)
+ {
+ return NRF_ERROR_NULL;
+ }
+
+ if (num_of_bytes == 0)
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+
+ if (mp_tx_buffer != NULL)
+ {
+ return NRF_ERROR_BUSY;
+ }
+
+ //ser_phy_interrupts_disable();
+ CRITICAL_REGION_ENTER();
+ mp_tx_buffer = (uint8_t *)p_buffer;
+ m_tx_buf_len = num_of_bytes;
+ m_pend_tx_api_flag = true;
+ SET_Pend_SW_IRQ();
+ //ser_phy_interrupts_enable();
+ CRITICAL_REGION_EXIT();
+
+ return NRF_SUCCESS;
+}
+/* ser_phy API function */
+uint32_t ser_phy_rx_buf_set(uint8_t * p_buffer)
+{
+ if (m_spi_master_state != SER_PHY_STATE_MEMORY_REQUEST)
+ {
+ return NRF_ERROR_INVALID_STATE;
+ }
+
+ //ser_phy_interrupts_disable();
+ CRITICAL_REGION_ENTER();
+ mp_rx_buffer = p_buffer;
+ m_pend_rx_api_flag = true;
+ SET_Pend_SW_IRQ();
+ //ser_phy_interrupts_enable();
+ CRITICAL_REGION_EXIT();
+
+ return NRF_SUCCESS;
+}
+
+/* ser_phy API function */
+uint32_t ser_phy_open(ser_phy_events_handler_t events_handler)
+{
+ if (m_spi_master_state != SER_PHY_STATE_DISABLED)
+ {
+ return NRF_ERROR_INVALID_STATE;
+ }
+
+ if (events_handler == NULL)
+ {
+ return NRF_ERROR_NULL;
+ }
+
+ uint32_t err_code = NRF_SUCCESS;
+
+ m_spi_master_state = SER_PHY_STATE_IDLE;
+ m_callback_events_handler = events_handler;
+ nrf_drv_spi_config_t spi_master_config = {
+ .sck_pin = SER_PHY_SPI_MASTER_PIN_SCK,
+ .mosi_pin = SER_PHY_SPI_MASTER_PIN_MOSI,
+ .miso_pin = SER_PHY_SPI_MASTER_PIN_MISO,
+ .ss_pin = SER_PHY_SPI_MASTER_PIN_SLAVE_SELECT,
+ .irq_priority = APP_IRQ_PRIORITY_MID,
+ .orc = 0,
+ .frequency = SER_PHY_SPI_FREQUENCY,
+ .mode = NRF_DRV_SPI_MODE_0,
+ .bit_order = NRF_DRV_SPI_BIT_ORDER_LSB_FIRST,
+ };
+ err_code = nrf_drv_spi_init(&m_spi_master,
+ &spi_master_config,
+ ser_phy_spi_master_event_handler,
+ NULL);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ err_code = ser_phy_init_gpiote();
+ ser_phy_init_PendSV();
+ return err_code;
+}
+
+/* ser_phy API function */
+void ser_phy_close(void)
+{
+ m_spi_master_state = SER_PHY_STATE_DISABLED;
+
+ m_callback_events_handler = NULL;
+
+ buffer_release(&mp_tx_buffer, &m_tx_buf_len);
+ buffer_release(&mp_rx_buffer, &m_rx_buf_len);
+
+ m_tx_packet_length = 0;
+ m_accumulated_tx_packet_length = 0;
+ m_current_tx_packet_length = 0;
+
+ m_rx_packet_length = 0;
+ m_accumulated_rx_packet_length = 0;
+ m_current_rx_packet_length = 0;
+
+ ser_phy_deinit_gpiote();
+ nrf_drv_spi_uninit(&m_spi_master);
+}
+
+/* ser_phy API function */
+/* only PendSV may interact with ser_phy layer, other interrupts are internal */
+void ser_phy_interrupts_enable(void)
+{
+ NVIC_EnableIRQ(SW_IRQn);
+}
+
+/* ser_phy API function */
+void ser_phy_interrupts_disable(void)
+{
+ NVIC_DisableIRQ(SW_IRQn);
+}
+
+/** @} */