Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Serialization, request connectivity chip status

On our custom board it can happen that an ASSERT triggers (suspect UART error due to EMC injection) on the connectivity chip, this meas that the application controller is no longer in sync with the connectivity controller and as a result triggers ASSERT's or HardFaults on the application controller.

Is there an api or serialization function available to request the status of the connectivity chip?

- SD enabled

- Characteristic available

 If this is function does not exist can you give me tip how i can add in our code.

Thanks in advance,

Erwin 

Parents
  • Hi,

    There is no such function.

    You would get some more robustness with UART HCI, compared to UART RAW.

    Since you get a reset on assert/hardfault, you can make the connectivity firmware send a signal on boot. Either over the same channel as the serialization, or use a separate line. When receiving that message/signal, you know that the connectivity is reset and thus that everything is uninitialized.

    Apart from that you could to some extent probe the status by calling API calls that depend on a particular state, and check the return value.

    Regards,
    Terje

  • The scary part is that we are already using UART HCI, but we've already made the following changes to the SDK to get the proper timeout behavior, because by default the serialization application (after porting) got stuck after the connectivity chip went out sync.

    Index: components/serialization/application/transport/ser_softdevice_handler.c
    ===================================================================
    --- components/serialization/application/transport/ser_softdevice_handler.c	(revision 683)
    +++ components/serialization/application/transport/ser_softdevice_handler.c	(revision 684)
    @@ -56,6 +56,9 @@
     #include "ant_event.h"
     #endif
     
    +#include "timer.h"
    +#include "app_messageprinting.h"
    +
     #define SD_BLE_EVT_MAILBOX_QUEUE_SIZE 5 /**< Size of mailbox queue. */
     
     /** @brief Structure used to pass packet details through mailbox.
    @@ -99,6 +102,8 @@
                   SD_BLE_EVT_MAILBOX_QUEUE_SIZE,
                   NRF_QUEUE_MODE_NO_OVERFLOW);
     
    +extern void ser_sd_transport_cmd_abort(void);
    +
     /**
      * @brief Function to be replaced by user implementation if needed.
      *
    @@ -183,11 +188,18 @@
      */
     static void ser_sd_rsp_wait(void)
     {
    +  uint32_t lvStartTime = Timer_GetMilliTime();
         do
         {
    -        (void)sd_app_evt_wait();
    +      (void)sd_app_evt_wait();
     
    -        //intern_softdevice_events_execute();
    +      //intern_softdevice_events_execute();
    +      if(Timer_GetMilliTimeDifference(lvStartTime,Timer_GetMilliTime()) > 2000)
    +      {
    +        MSG_BLE_ERROR("ser_sd_rsp_wait: timeout");
    +        ser_sd_transport_cmd_abort();
    +      }
    +      
         }
         while (ser_sd_transport_is_busy());
     }
    Index: components/serialization/application/transport/ser_sd_transport.c
    ===================================================================
    --- components/serialization/application/transport/ser_sd_transport.c	(revision 683)
    +++ components/serialization/application/transport/ser_sd_transport.c	(revision 684)
    @@ -292,6 +292,12 @@
         return ser_hal_transport_rx_pkt_free(p_data);
     }
     
    +void ser_sd_transport_cmd_abort(void)
    +{
    +  m_return_value = NRF_ERROR_INTERNAL;
    +  m_rsp_wait = false;
    +}
    +
     uint32_t ser_sd_transport_cmd_write(const uint8_t *                p_buffer,
                                         uint16_t                       length,
                                         ser_sd_transport_rsp_handler_t cmd_rsp_decode_callback)
    
    
    Index: components/serialization/application/transport/ser_sd_transport.c
    ===================================================================
    --- components/serialization/application/transport/ser_sd_transport.c	(revision 716)
    +++ components/serialization/application/transport/ser_sd_transport.c	(revision 717)
    @@ -294,6 +294,7 @@
     
     void ser_sd_transport_cmd_abort(void)
     {
    +  ser_hal_transport_tx_abort();
       m_return_value = NRF_ERROR_INTERNAL;
       m_rsp_wait = false;
     }
    Index: components/serialization/common/transport/ser_hal_transport.h
    ===================================================================
    --- components/serialization/common/transport/ser_hal_transport.h	(revision 716)
    +++ components/serialization/common/transport/ser_hal_transport.h	(revision 717)
    @@ -256,8 +256,8 @@
      */
     uint32_t ser_hal_transport_tx_pkt_free(uint8_t * p_buffer);
     
    +void ser_hal_transport_tx_abort(void);
     
    -
     #ifdef __cplusplus
     }
     #endif
    Index: components/serialization/common/transport/ser_phy/ser_phy_hci_slip.c
    ===================================================================
    --- components/serialization/common/transport/ser_phy/ser_phy_hci_slip.c	(revision 716)
    +++ components/serialization/common/transport/ser_phy/ser_phy_hci_slip.c	(revision 717)
    @@ -595,7 +595,37 @@
                     APP_ERROR_CHECK(nrf_drv_uart_rx(&m_uart, m_rx_buf, 1));
                     break;
                 }
    +            else if(p_event->data.error.error_mask &
    +                (NRF_UART_ERROR_TIMEOUT_MASK))
    +            {
    +                // Pass error source to upper layer
    +                m_ser_phy_hci_slip_event.evt_type =
    +                    SER_PHY_HCI_SLIP_EVT_HW_ERROR;
    +                m_ser_phy_hci_slip_event.evt_params.hw_error.error_code =
    +                    p_event->data.error.error_mask;
    +                m_ser_phy_hci_slip_event_handler(&m_ser_phy_hci_slip_event);
    +              
    +                APP_ERROR_CHECK(nrf_drv_uart_rx(&m_uart, m_rx_buf, 1));
    +              
    +                if (m_tx_pending)
    +                {
    +                    // Switch to the buffer that has just been sent completely
    +                    // and now can be filled again.
    +                    mp_tx_buf = (mp_tx_buf == m_tx_buf0) ? m_tx_buf1 : m_tx_buf0;
    +                    m_tx_bytes = 0;
    +
    +                    m_tx_pending = false;
    +                }
    +                m_tx_in_progress = false;
    +              
    +                if (m_tx_phase != PHASE_IDLE)
    +                {
    +                    tx_buf_fill();
    +                }
    +                break;
    +            }
                 APP_ERROR_CHECK(nrf_drv_uart_rx(&m_uart, m_rx_buf, 1));
    +            break;
             case NRF_DRV_UART_EVT_TX_DONE:
                 // If there is a pending transfer (the second buffer is ready to
                 // be sent), start it immediately.
    Index: components/serialization/common/transport/ser_phy/ser_phy_hci.c
    ===================================================================
    --- components/serialization/common/transport/ser_phy/ser_phy_hci.c	(revision 716)
    +++ components/serialization/common/transport/ser_phy/ser_phy_hci.c	(revision 717)
    @@ -736,6 +736,7 @@
     
         event.evt_type = SER_PHY_EVT_HW_ERROR;
         event.evt_params.hw_error.p_buffer = m_p_tx_payload;
    +    m_p_tx_payload = NULL;
         ser_phy_event_callback(event);
     }
     
    @@ -863,7 +864,8 @@
         }
         else
         {
    -        NRF_LOG_DEBUG("EVT_HW_ERROR");
    +      NRF_LOG_DEBUG("EVT_HW_ERROR");
    +      hci_signal_timeout_event();
         }
     }
     
    @@ -1014,6 +1016,11 @@
                 {
                     hci_process_orphaned_ack(p_event);
                 }
    +            else if (p_event->evt_source == HCI_TIMER_EVT)
    +            {
    +              error_callback();
    +              m_hci_tx_fsm_state = HCI_TX_STATE_SEND;
    +            }                
                 break;
     
             case HCI_TX_STATE_WAIT_FOR_ACK_OR_TX_END:
    @@ -1688,10 +1695,12 @@
     /* ser_phy API function */
     void ser_phy_close(void)
     {
    +    m_p_tx_payload     = NULL;
         m_ser_phy_callback = NULL;
         ser_phy_hci_slip_close();
         m_hci_tx_fsm_state = HCI_TX_STATE_DISABLE;
         m_hci_rx_fsm_state = HCI_RX_STATE_DISABLE;
    +  
     
     #ifdef HCI_LINK_CONTROL
         m_hci_mode         = HCI_MODE_DISABLE;
    Index: components/serialization/common/transport/ser_hal_transport.c
    ===================================================================
    --- components/serialization/common/transport/ser_hal_transport.c	(revision 716)
    +++ components/serialization/common/transport/ser_hal_transport.c	(revision 717)
    @@ -285,7 +285,7 @@
                     APP_ERROR_CHECK(err_code);
                 }
                 m_events_handler(hal_transp_event);
    -
    +            
                 break;
             }
     
    @@ -334,7 +334,7 @@
                 }
             }
         }
    -
    +    
         return err_code;
     }
     
    @@ -501,3 +501,9 @@
     
         return err_code;
     }
    +
    +void ser_hal_transport_tx_abort(void)
    +{
    +  /* Release TX buffer for use. */
    +  m_tx_state = HAL_TRANSP_TX_STATE_IDLE;
    +}
    
    
    Index: components/serialization/common/transport/ser_phy/ser_phy.h
    ===================================================================
    --- components/serialization/common/transport/ser_phy/ser_phy.h	(revision 719)
    +++ components/serialization/common/transport/ser_phy/ser_phy.h	(revision 720)
    @@ -285,6 +285,13 @@
     void ser_phy_close(void);
     
     
    +/**@brief Function for aborting pending transmission.
    + *
    + * @note  
    + */
    +void ser_phy_abort(void);
    +
    +
     /**@brief Function for enabling the PHY module interrupts.
      *
      * @note  The function enables all interrupts that are used by the PHY module (and only those).
    Index: components/serialization/common/transport/ser_phy/ser_phy_hci.c
    ===================================================================
    --- components/serialization/common/transport/ser_phy/ser_phy_hci.c	(revision 719)
    +++ components/serialization/common/transport/ser_phy/ser_phy_hci.c	(revision 720)
    @@ -1710,4 +1710,9 @@
         ser_phy_hci_assert(err_code == NRF_SUCCESS);
     }
     
    +void ser_phy_abort(void)
    +{
    +  error_callback();
    +}
     
    +
    Index: components/serialization/common/transport/ser_hal_transport.c
    ===================================================================
    --- components/serialization/common/transport/ser_hal_transport.c	(revision 719)
    +++ components/serialization/common/transport/ser_hal_transport.c	(revision 720)
    @@ -506,4 +506,7 @@
     {
       /* Release TX buffer for use. */
       m_tx_state = HAL_TRANSP_TX_STATE_IDLE;
    +  
    +  /* Release Tx buffer lower layer. */
    +  ser_phy_abort();
     }
    

    We're not sure why we had to add these steps to the SDK, but now the blocking Tx and Rx functions are protected and free the SDK after either timeout has elapsed.

    Thanks for the tip, we were already afraid that there was no function available to poll this situation, so we've added a interval timer that checks the advertising name to see if the controllers are still in sync.

    Regards,

    Erwin

Reply
  • The scary part is that we are already using UART HCI, but we've already made the following changes to the SDK to get the proper timeout behavior, because by default the serialization application (after porting) got stuck after the connectivity chip went out sync.

    Index: components/serialization/application/transport/ser_softdevice_handler.c
    ===================================================================
    --- components/serialization/application/transport/ser_softdevice_handler.c	(revision 683)
    +++ components/serialization/application/transport/ser_softdevice_handler.c	(revision 684)
    @@ -56,6 +56,9 @@
     #include "ant_event.h"
     #endif
     
    +#include "timer.h"
    +#include "app_messageprinting.h"
    +
     #define SD_BLE_EVT_MAILBOX_QUEUE_SIZE 5 /**< Size of mailbox queue. */
     
     /** @brief Structure used to pass packet details through mailbox.
    @@ -99,6 +102,8 @@
                   SD_BLE_EVT_MAILBOX_QUEUE_SIZE,
                   NRF_QUEUE_MODE_NO_OVERFLOW);
     
    +extern void ser_sd_transport_cmd_abort(void);
    +
     /**
      * @brief Function to be replaced by user implementation if needed.
      *
    @@ -183,11 +188,18 @@
      */
     static void ser_sd_rsp_wait(void)
     {
    +  uint32_t lvStartTime = Timer_GetMilliTime();
         do
         {
    -        (void)sd_app_evt_wait();
    +      (void)sd_app_evt_wait();
     
    -        //intern_softdevice_events_execute();
    +      //intern_softdevice_events_execute();
    +      if(Timer_GetMilliTimeDifference(lvStartTime,Timer_GetMilliTime()) > 2000)
    +      {
    +        MSG_BLE_ERROR("ser_sd_rsp_wait: timeout");
    +        ser_sd_transport_cmd_abort();
    +      }
    +      
         }
         while (ser_sd_transport_is_busy());
     }
    Index: components/serialization/application/transport/ser_sd_transport.c
    ===================================================================
    --- components/serialization/application/transport/ser_sd_transport.c	(revision 683)
    +++ components/serialization/application/transport/ser_sd_transport.c	(revision 684)
    @@ -292,6 +292,12 @@
         return ser_hal_transport_rx_pkt_free(p_data);
     }
     
    +void ser_sd_transport_cmd_abort(void)
    +{
    +  m_return_value = NRF_ERROR_INTERNAL;
    +  m_rsp_wait = false;
    +}
    +
     uint32_t ser_sd_transport_cmd_write(const uint8_t *                p_buffer,
                                         uint16_t                       length,
                                         ser_sd_transport_rsp_handler_t cmd_rsp_decode_callback)
    
    
    Index: components/serialization/application/transport/ser_sd_transport.c
    ===================================================================
    --- components/serialization/application/transport/ser_sd_transport.c	(revision 716)
    +++ components/serialization/application/transport/ser_sd_transport.c	(revision 717)
    @@ -294,6 +294,7 @@
     
     void ser_sd_transport_cmd_abort(void)
     {
    +  ser_hal_transport_tx_abort();
       m_return_value = NRF_ERROR_INTERNAL;
       m_rsp_wait = false;
     }
    Index: components/serialization/common/transport/ser_hal_transport.h
    ===================================================================
    --- components/serialization/common/transport/ser_hal_transport.h	(revision 716)
    +++ components/serialization/common/transport/ser_hal_transport.h	(revision 717)
    @@ -256,8 +256,8 @@
      */
     uint32_t ser_hal_transport_tx_pkt_free(uint8_t * p_buffer);
     
    +void ser_hal_transport_tx_abort(void);
     
    -
     #ifdef __cplusplus
     }
     #endif
    Index: components/serialization/common/transport/ser_phy/ser_phy_hci_slip.c
    ===================================================================
    --- components/serialization/common/transport/ser_phy/ser_phy_hci_slip.c	(revision 716)
    +++ components/serialization/common/transport/ser_phy/ser_phy_hci_slip.c	(revision 717)
    @@ -595,7 +595,37 @@
                     APP_ERROR_CHECK(nrf_drv_uart_rx(&m_uart, m_rx_buf, 1));
                     break;
                 }
    +            else if(p_event->data.error.error_mask &
    +                (NRF_UART_ERROR_TIMEOUT_MASK))
    +            {
    +                // Pass error source to upper layer
    +                m_ser_phy_hci_slip_event.evt_type =
    +                    SER_PHY_HCI_SLIP_EVT_HW_ERROR;
    +                m_ser_phy_hci_slip_event.evt_params.hw_error.error_code =
    +                    p_event->data.error.error_mask;
    +                m_ser_phy_hci_slip_event_handler(&m_ser_phy_hci_slip_event);
    +              
    +                APP_ERROR_CHECK(nrf_drv_uart_rx(&m_uart, m_rx_buf, 1));
    +              
    +                if (m_tx_pending)
    +                {
    +                    // Switch to the buffer that has just been sent completely
    +                    // and now can be filled again.
    +                    mp_tx_buf = (mp_tx_buf == m_tx_buf0) ? m_tx_buf1 : m_tx_buf0;
    +                    m_tx_bytes = 0;
    +
    +                    m_tx_pending = false;
    +                }
    +                m_tx_in_progress = false;
    +              
    +                if (m_tx_phase != PHASE_IDLE)
    +                {
    +                    tx_buf_fill();
    +                }
    +                break;
    +            }
                 APP_ERROR_CHECK(nrf_drv_uart_rx(&m_uart, m_rx_buf, 1));
    +            break;
             case NRF_DRV_UART_EVT_TX_DONE:
                 // If there is a pending transfer (the second buffer is ready to
                 // be sent), start it immediately.
    Index: components/serialization/common/transport/ser_phy/ser_phy_hci.c
    ===================================================================
    --- components/serialization/common/transport/ser_phy/ser_phy_hci.c	(revision 716)
    +++ components/serialization/common/transport/ser_phy/ser_phy_hci.c	(revision 717)
    @@ -736,6 +736,7 @@
     
         event.evt_type = SER_PHY_EVT_HW_ERROR;
         event.evt_params.hw_error.p_buffer = m_p_tx_payload;
    +    m_p_tx_payload = NULL;
         ser_phy_event_callback(event);
     }
     
    @@ -863,7 +864,8 @@
         }
         else
         {
    -        NRF_LOG_DEBUG("EVT_HW_ERROR");
    +      NRF_LOG_DEBUG("EVT_HW_ERROR");
    +      hci_signal_timeout_event();
         }
     }
     
    @@ -1014,6 +1016,11 @@
                 {
                     hci_process_orphaned_ack(p_event);
                 }
    +            else if (p_event->evt_source == HCI_TIMER_EVT)
    +            {
    +              error_callback();
    +              m_hci_tx_fsm_state = HCI_TX_STATE_SEND;
    +            }                
                 break;
     
             case HCI_TX_STATE_WAIT_FOR_ACK_OR_TX_END:
    @@ -1688,10 +1695,12 @@
     /* ser_phy API function */
     void ser_phy_close(void)
     {
    +    m_p_tx_payload     = NULL;
         m_ser_phy_callback = NULL;
         ser_phy_hci_slip_close();
         m_hci_tx_fsm_state = HCI_TX_STATE_DISABLE;
         m_hci_rx_fsm_state = HCI_RX_STATE_DISABLE;
    +  
     
     #ifdef HCI_LINK_CONTROL
         m_hci_mode         = HCI_MODE_DISABLE;
    Index: components/serialization/common/transport/ser_hal_transport.c
    ===================================================================
    --- components/serialization/common/transport/ser_hal_transport.c	(revision 716)
    +++ components/serialization/common/transport/ser_hal_transport.c	(revision 717)
    @@ -285,7 +285,7 @@
                     APP_ERROR_CHECK(err_code);
                 }
                 m_events_handler(hal_transp_event);
    -
    +            
                 break;
             }
     
    @@ -334,7 +334,7 @@
                 }
             }
         }
    -
    +    
         return err_code;
     }
     
    @@ -501,3 +501,9 @@
     
         return err_code;
     }
    +
    +void ser_hal_transport_tx_abort(void)
    +{
    +  /* Release TX buffer for use. */
    +  m_tx_state = HAL_TRANSP_TX_STATE_IDLE;
    +}
    
    
    Index: components/serialization/common/transport/ser_phy/ser_phy.h
    ===================================================================
    --- components/serialization/common/transport/ser_phy/ser_phy.h	(revision 719)
    +++ components/serialization/common/transport/ser_phy/ser_phy.h	(revision 720)
    @@ -285,6 +285,13 @@
     void ser_phy_close(void);
     
     
    +/**@brief Function for aborting pending transmission.
    + *
    + * @note  
    + */
    +void ser_phy_abort(void);
    +
    +
     /**@brief Function for enabling the PHY module interrupts.
      *
      * @note  The function enables all interrupts that are used by the PHY module (and only those).
    Index: components/serialization/common/transport/ser_phy/ser_phy_hci.c
    ===================================================================
    --- components/serialization/common/transport/ser_phy/ser_phy_hci.c	(revision 719)
    +++ components/serialization/common/transport/ser_phy/ser_phy_hci.c	(revision 720)
    @@ -1710,4 +1710,9 @@
         ser_phy_hci_assert(err_code == NRF_SUCCESS);
     }
     
    +void ser_phy_abort(void)
    +{
    +  error_callback();
    +}
     
    +
    Index: components/serialization/common/transport/ser_hal_transport.c
    ===================================================================
    --- components/serialization/common/transport/ser_hal_transport.c	(revision 719)
    +++ components/serialization/common/transport/ser_hal_transport.c	(revision 720)
    @@ -506,4 +506,7 @@
     {
       /* Release TX buffer for use. */
       m_tx_state = HAL_TRANSP_TX_STATE_IDLE;
    +  
    +  /* Release Tx buffer lower layer. */
    +  ser_phy_abort();
     }
    

    We're not sure why we had to add these steps to the SDK, but now the blocking Tx and Rx functions are protected and free the SDK after either timeout has elapsed.

    Thanks for the tip, we were already afraid that there was no function available to poll this situation, so we've added a interval timer that checks the advertising name to see if the controllers are still in sync.

    Regards,

    Erwin

Children
Related