515 lines
17 KiB
C
Raw Permalink Normal View History

2025-08-19 09:49:41 +08:00
/**
* Copyright (c) 2014 - 2020, 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"
#if defined(APP_SCHEDULER_WITH_PAUSE) && APP_SCHEDULER_WITH_PAUSE
#include "app_scheduler.h"
#endif
#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);
#if defined(APP_SCHEDULER_WITH_PAUSE) && APP_SCHEDULER_WITH_PAUSE
app_sched_resume();
#endif
/* 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;
}
}
}
void ser_hal_transport_reset(void)
{
m_rx_state = HAL_TRANSP_RX_STATE_IDLE;
m_tx_state = HAL_TRANSP_TX_STATE_IDLE;
}
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;
}