diff options
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/serialization/common/transport/ser_hal_transport.c')
-rw-r--r-- | thirdparty/nRF5_SDK_15.0.0_a53641a/components/serialization/common/transport/ser_hal_transport.c | 503 |
1 files changed, 503 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/serialization/common/transport/ser_hal_transport.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/serialization/common/transport/ser_hal_transport.c new file mode 100644 index 0000000..0a8bc16 --- /dev/null +++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/serialization/common/transport/ser_hal_transport.c @@ -0,0 +1,503 @@ +/** + * 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. + * + */ +#include <stdbool.h> +#include <string.h> +#include "app_error.h" +#include "sdk_config.h" +#include "ser_config.h" +#include "ser_phy.h" +#include "ser_hal_transport.h" + +#define NRF_LOG_MODULE_NAME ser_hal_transport +#if SER_HAL_TRANSPORT_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL SER_HAL_TRANSPORT_CONFIG_LOG_LEVEL + #define NRF_LOG_INFO_COLOR SER_HAL_TRANSPORT_CONFIG_INFO_COLOR + #define NRF_LOG_DEBUG_COLOR SER_HAL_TRANSPORT_CONFIG_DEBUG_COLOR +#else //SER_HAL_TRANSPORT_CONFIG_LOG_ENABLED + #define NRF_LOG_LEVEL 0 +#endif //SER_HAL_TRANSPORT_CONFIG_LOG_ENABLED +#include "nrf_log.h" +NRF_LOG_MODULE_REGISTER(); + +/** + * @brief States of the RX state machine. + */ +typedef enum +{ + HAL_TRANSP_RX_STATE_CLOSED = 0, + HAL_TRANSP_RX_STATE_IDLE, + HAL_TRANSP_RX_STATE_RECEIVING, + HAL_TRANSP_RX_STATE_DROPPING, + HAL_TRANSP_RX_STATE_RECEIVED, + HAL_TRANSP_RX_STATE_RECEIVED_PENDING_BUF_REQ, + HAL_TRANSP_RX_STATE_RECEIVED_DROPPING, + HAL_TRANSP_RX_STATE_MAX +}ser_hal_transp_rx_states_t; + +/** + * @brief States of the TX state machine. + */ +typedef enum +{ + HAL_TRANSP_TX_STATE_CLOSED = 0, + HAL_TRANSP_TX_STATE_IDLE, + HAL_TRANSP_TX_STATE_TX_ALLOCATED, + HAL_TRANSP_TX_STATE_TRANSMITTING, + HAL_TRANSP_TX_STATE_TRANSMITTED, + HAL_TRANSP_TX_STATE_MAX +}ser_hal_transp_tx_states_t; + +/** + * @brief RX state. + */ +static ser_hal_transp_rx_states_t m_rx_state = HAL_TRANSP_RX_STATE_CLOSED; +/** + * @brief TX state. + */ +static ser_hal_transp_tx_states_t m_tx_state = HAL_TRANSP_TX_STATE_CLOSED; + +/** + * @brief Transmission buffer. + */ +static uint8_t m_tx_buffer[SER_HAL_TRANSPORT_TX_MAX_PKT_SIZE]; +/** + * @brief Reception buffer. + */ +static uint8_t m_rx_buffer[SER_HAL_TRANSPORT_RX_MAX_PKT_SIZE]; + +/** + * @brief Callback function handler for Serialization HAL Transport layer events. + */ +static ser_hal_transport_events_handler_t m_events_handler = NULL; + + +/** + * @brief A callback function to be used to handle a PHY module events. This function is called in + * an interrupt context. + */ +static void phy_events_handler(ser_phy_evt_t phy_event) +{ + uint32_t err_code = 0; + ser_hal_transport_evt_t hal_transp_event; + + memset(&hal_transp_event, 0, sizeof (ser_hal_transport_evt_t)); + hal_transp_event.evt_type = SER_HAL_TRANSP_EVT_TYPE_MAX; + + NRF_LOG_INFO("phy evt:%d", phy_event.evt_type); + switch (phy_event.evt_type) + { + case SER_PHY_EVT_TX_PKT_SENT: + { + if (HAL_TRANSP_TX_STATE_TRANSMITTING == m_tx_state) + { + m_tx_state = HAL_TRANSP_TX_STATE_TRANSMITTED; + NRF_LOG_INFO("tx free"); + err_code = ser_hal_transport_tx_pkt_free(m_tx_buffer); + APP_ERROR_CHECK(err_code); + /* An event to an upper layer that a packet has been transmitted. */ + hal_transp_event.evt_type = SER_HAL_TRANSP_EVT_TX_PKT_SENT; + m_events_handler(hal_transp_event); + } + else + { + /* Lower layer should not generate this event in current state. */ + APP_ERROR_CHECK_BOOL(false); + } + break; + } + + case SER_PHY_EVT_RX_BUF_REQUEST: + { + /* An event to an upper layer that a packet is being scheduled to receive or to drop. */ + hal_transp_event.evt_type = SER_HAL_TRANSP_EVT_RX_PKT_RECEIVING; + + /* Receive or drop a packet. */ + if (phy_event.evt_params.rx_buf_request.num_of_bytes <= sizeof (m_rx_buffer)) + { + if (HAL_TRANSP_RX_STATE_IDLE == m_rx_state) + { + m_events_handler(hal_transp_event); + err_code = ser_phy_rx_buf_set(m_rx_buffer); + APP_ERROR_CHECK(err_code); + m_rx_state = HAL_TRANSP_RX_STATE_RECEIVING; + } + else if (HAL_TRANSP_RX_STATE_RECEIVED == m_rx_state) + { + /* It is OK to get know higher layer at this point that we are going to receive + * a new packet even though we will start receiving when rx buffer is freed. */ + m_events_handler(hal_transp_event); + m_rx_state = HAL_TRANSP_RX_STATE_RECEIVED_PENDING_BUF_REQ; + } + else + { + /* Lower layer should not generate this event in current state. */ + APP_ERROR_CHECK_BOOL(false); + } + } + else + { + /* There is not enough memory but packet has to be received to dummy location. */ + if (HAL_TRANSP_RX_STATE_IDLE == m_rx_state) + { + m_events_handler(hal_transp_event); + err_code = ser_phy_rx_buf_set(NULL); + APP_ERROR_CHECK(err_code); + m_rx_state = HAL_TRANSP_RX_STATE_DROPPING; + } + else if (HAL_TRANSP_RX_STATE_RECEIVED == m_rx_state) + { + m_events_handler(hal_transp_event); + err_code = ser_phy_rx_buf_set(NULL); + APP_ERROR_CHECK(err_code); + m_rx_state = HAL_TRANSP_RX_STATE_RECEIVED_DROPPING; + } + else + { + /* Lower layer should not generate this event in current state. */ + APP_ERROR_CHECK_BOOL(false); + } + } + break; + } + + case SER_PHY_EVT_RX_PKT_RECEIVED: + { + if (HAL_TRANSP_RX_STATE_RECEIVING == m_rx_state) + { + m_rx_state = HAL_TRANSP_RX_STATE_RECEIVED; + /* Generate the event to an upper layer. */ + hal_transp_event.evt_type = + SER_HAL_TRANSP_EVT_RX_PKT_RECEIVED; + hal_transp_event.evt_params.rx_pkt_received.p_buffer = + phy_event.evt_params.rx_pkt_received.p_buffer; + hal_transp_event.evt_params.rx_pkt_received.num_of_bytes = + phy_event.evt_params.rx_pkt_received.num_of_bytes; + m_events_handler(hal_transp_event); + } + else + { + /* Lower layer should not generate this event in current state. */ + APP_ERROR_CHECK_BOOL(false); + } + break; + } + + case SER_PHY_EVT_RX_PKT_DROPPED: + { + if (HAL_TRANSP_RX_STATE_DROPPING == m_rx_state) + { + /* Generate the event to an upper layer. */ + hal_transp_event.evt_type = SER_HAL_TRANSP_EVT_RX_PKT_DROPPED; + m_events_handler(hal_transp_event); + m_rx_state = HAL_TRANSP_RX_STATE_IDLE; + } + else if (HAL_TRANSP_RX_STATE_RECEIVED_DROPPING == m_rx_state) + { + /* Generate the event to an upper layer. */ + hal_transp_event.evt_type = SER_HAL_TRANSP_EVT_RX_PKT_DROPPED; + m_events_handler(hal_transp_event); + m_rx_state = HAL_TRANSP_RX_STATE_RECEIVED; + } + else + { + /* Lower layer should not generate this event in current state. */ + APP_ERROR_CHECK_BOOL(false); + } + break; + } + + case SER_PHY_EVT_RX_OVERFLOW_ERROR: + { + /* Generate the event to an upper layer. */ + hal_transp_event.evt_type = SER_HAL_TRANSP_EVT_PHY_ERROR; + hal_transp_event.evt_params.phy_error.error_type = + SER_HAL_TRANSP_PHY_ERROR_RX_OVERFLOW; + m_events_handler(hal_transp_event); + break; + } + + case SER_PHY_EVT_TX_OVERREAD_ERROR: + { + /* Generate the event to an upper layer. */ + hal_transp_event.evt_type = SER_HAL_TRANSP_EVT_PHY_ERROR; + hal_transp_event.evt_params.phy_error.error_type = + SER_HAL_TRANSP_PHY_ERROR_TX_OVERREAD; + m_events_handler(hal_transp_event); + break; + } + + case SER_PHY_EVT_HW_ERROR: + { + /* Generate the event to an upper layer. */ + hal_transp_event.evt_type = SER_HAL_TRANSP_EVT_PHY_ERROR; + hal_transp_event.evt_params.phy_error.error_type = + SER_HAL_TRANSP_PHY_ERROR_HW_ERROR; + hal_transp_event.evt_params.phy_error.hw_error_code = + phy_event.evt_params.hw_error.error_code; + if (HAL_TRANSP_TX_STATE_TRANSMITTING == m_tx_state) + { + m_tx_state = HAL_TRANSP_TX_STATE_TRANSMITTED; + err_code = ser_hal_transport_tx_pkt_free(phy_event.evt_params.hw_error.p_buffer); + APP_ERROR_CHECK(err_code); + /* An event to an upper layer that a packet has been transmitted. */ + } + else if (HAL_TRANSP_RX_STATE_RECEIVING == m_rx_state) + { + m_rx_state = HAL_TRANSP_RX_STATE_RECEIVED; + err_code = ser_hal_transport_rx_pkt_free(phy_event.evt_params.hw_error.p_buffer); + APP_ERROR_CHECK(err_code); + } + m_events_handler(hal_transp_event); + + break; + } + + default: + { + APP_ERROR_CHECK_BOOL(false); + break; + } + } +} + +uint32_t ser_hal_transport_open(ser_hal_transport_events_handler_t events_handler) +{ + uint32_t err_code = NRF_SUCCESS; + + if ((HAL_TRANSP_RX_STATE_CLOSED != m_rx_state) || (HAL_TRANSP_TX_STATE_CLOSED != m_tx_state)) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else if (NULL == events_handler) + { + err_code = NRF_ERROR_NULL; + } + else + { + /* We have to change states before calling lower layer because ser_phy_open() function is + * going to enable interrupts. On success an event from PHY layer can be emitted immediately + * after return from ser_phy_open(). */ + m_rx_state = HAL_TRANSP_RX_STATE_IDLE; + m_tx_state = HAL_TRANSP_TX_STATE_IDLE; + + m_events_handler = events_handler; + + /* Initialize a PHY module. */ + err_code = ser_phy_open(phy_events_handler); + + if (NRF_SUCCESS != err_code) + { + m_rx_state = HAL_TRANSP_RX_STATE_CLOSED; + m_tx_state = HAL_TRANSP_TX_STATE_CLOSED; + m_events_handler = NULL; + + if (NRF_ERROR_INVALID_PARAM != err_code) + { + err_code = NRF_ERROR_INTERNAL; + } + } + } + + return err_code; +} + + +void ser_hal_transport_close(void) +{ + /* Reset generic handler for all events, reset internal states and close PHY module. */ + ser_phy_interrupts_disable(); + m_rx_state = HAL_TRANSP_RX_STATE_CLOSED; + m_tx_state = HAL_TRANSP_TX_STATE_CLOSED; + + m_events_handler = NULL; + + ser_phy_close(); +} + + +uint32_t ser_hal_transport_rx_pkt_free(uint8_t * p_buffer) +{ + + NRF_LOG_INFO("rx pkt free:%d", p_buffer); + uint32_t err_code = NRF_SUCCESS; + + ser_phy_interrupts_disable(); + + if (NULL == p_buffer) + { + err_code = NRF_ERROR_NULL; + } + else if (p_buffer != m_rx_buffer) + { + err_code = NRF_ERROR_INVALID_ADDR; + } + else if (HAL_TRANSP_RX_STATE_RECEIVED == m_rx_state) + { + m_rx_state = HAL_TRANSP_RX_STATE_IDLE; + } + else if (HAL_TRANSP_RX_STATE_RECEIVED_DROPPING == m_rx_state) + { + m_rx_state = HAL_TRANSP_RX_STATE_DROPPING; + } + else if (HAL_TRANSP_RX_STATE_RECEIVED_PENDING_BUF_REQ == m_rx_state) + { + err_code = ser_phy_rx_buf_set(m_rx_buffer); + + if (NRF_SUCCESS == err_code) + { + m_rx_state = HAL_TRANSP_RX_STATE_RECEIVING; + } + else + { + err_code = NRF_ERROR_INTERNAL; + } + } + else + { + /* Upper layer should not call this function in current state. */ + err_code = NRF_ERROR_INVALID_STATE; + } + ser_phy_interrupts_enable(); + + return err_code; +} + + +uint32_t ser_hal_transport_tx_pkt_alloc(uint8_t * * pp_memory, uint16_t * p_num_of_bytes) +{ + uint32_t err_code = NRF_SUCCESS; + + if ((NULL == pp_memory) || (NULL == p_num_of_bytes)) + { + err_code = NRF_ERROR_NULL; + } + else if (HAL_TRANSP_TX_STATE_CLOSED == m_tx_state) + { + err_code = NRF_ERROR_INVALID_STATE; + } + else if (HAL_TRANSP_TX_STATE_IDLE == m_tx_state) + { + m_tx_state = HAL_TRANSP_TX_STATE_TX_ALLOCATED; + *pp_memory = &m_tx_buffer[0]; + *p_num_of_bytes = (uint16_t)sizeof (m_tx_buffer); + } + else + { + err_code = NRF_ERROR_NO_MEM; + } + + return err_code; +} + + +uint32_t ser_hal_transport_tx_pkt_send(const uint8_t * p_buffer, uint16_t num_of_bytes) +{ + uint32_t err_code = NRF_SUCCESS; + + /* The buffer provided to this function must be allocated through ser_hal_transport_tx_alloc() + * function - this assures correct state and that correct memory buffer is used. */ + if (NULL == p_buffer) + { + err_code = NRF_ERROR_NULL; + } + else if (0 == num_of_bytes) + { + err_code = NRF_ERROR_INVALID_PARAM; + } + else if (p_buffer != m_tx_buffer) + { + err_code = NRF_ERROR_INVALID_ADDR; + } + else if (num_of_bytes > sizeof (m_tx_buffer)) + { + err_code = NRF_ERROR_DATA_SIZE; + } + else if (HAL_TRANSP_TX_STATE_TX_ALLOCATED == m_tx_state) + { + ser_phy_interrupts_disable(); + err_code = ser_phy_tx_pkt_send(p_buffer, num_of_bytes); + + if (NRF_SUCCESS == err_code) + { + m_tx_state = HAL_TRANSP_TX_STATE_TRANSMITTING; + } + else + { + if (NRF_ERROR_BUSY != err_code) + { + err_code = NRF_ERROR_INTERNAL; + } + } + ser_phy_interrupts_enable(); + } + else + { + err_code = NRF_ERROR_INVALID_STATE; + } + + return err_code; +} + + +uint32_t ser_hal_transport_tx_pkt_free(uint8_t * p_buffer) +{ + uint32_t err_code = NRF_SUCCESS; + + if (NULL == p_buffer) + { + err_code = NRF_ERROR_NULL; + } + else if (p_buffer != m_tx_buffer) + { + err_code = NRF_ERROR_INVALID_ADDR; + } + else if ((HAL_TRANSP_TX_STATE_TX_ALLOCATED == m_tx_state) || + (HAL_TRANSP_TX_STATE_TRANSMITTED == m_tx_state)) + { + /* Release TX buffer for use. */ + m_tx_state = HAL_TRANSP_TX_STATE_IDLE; + } + else + { + err_code = NRF_ERROR_INVALID_STATE; + } + + return err_code; +} |