This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Serial library nrf_serial_read() function behaves oddly

Good afternoon,

I am able to write data using polling mode with the macro NRF_SERIAL_CONFIG_DEF(serial_config, NRF_SERIAL_MODE_POLLING,  NULL, NULL, NULL, NULL). I am using the peripheral example serial program in the nrf5 SDK v15.0.0. I checked the UART lines with the Logic Analyzer and it shows bytes sending to and receiving from the machine. However I am not able to read the incoming data stream with the nrf_serial_read function. The function will block and never return.

The functionality I am trying to achieve is very trivial and does not need any complex queues and interrupt handlers. I just have to read and store data from the UART. An example or code snippet describing the nuances of the nrf_serial_read function would be very helpful.

Thank you in advance.

Sabine

/**
 * Copyright (c) 2016 - 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 <stddef.h>
#include <stdint.h>
//PPOS
#include <string.h>

#include "app_timer.h"
#include "nrf.h"
#include "nrf_delay.h"
#include "nrf_drv_clock.h"
#include "nrf_drv_power.h"
#include "nrf_gpio.h"
#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_serial.h"

#include "app_error.h"
#include "app_util.h"
#include "boards.h"
//PPOS
#include "zzsdk_config.h"

/** @file
 * @defgroup nrf_serial_example main.c
 * @{
 * @ingroup nrf_serial_example
 * @brief Example of @ref nrf_serial usage. 
 *
 */

#define OP_QUEUES_SIZE 3
#define APP_TIMER_PRESCALER NRF_SERIAL_APP_TIMER_PRESCALER

static void sleep_handler(void) {
  __WFE();
  __SEV();
  __WFE();
}

NRF_SERIAL_DRV_UART_CONFIG_DEF(m_uart0_drv_config,
    RX_PIN_NUMBER, TX_PIN_NUMBER,
    RTS_PIN_NUMBER, CTS_PIN_NUMBER,
    NRF_UART_HWFC_DISABLED,
    //NRF_UART_HWFC_ENABLED,
    NRF_UART_PARITY_EXCLUDED,
    //NRF_UART_BAUDRATE_115200,
    NRF_UART_BAUDRATE_9600,
    UART_DEFAULT_CONFIG_IRQ_PRIORITY);

#define SERIAL_FIFO_TX_SIZE 32
//#define SERIAL_FIFO_RX_SIZE 32
#define SERIAL_FIFO_RX_SIZE 48

NRF_SERIAL_QUEUES_DEF(serial_queues, SERIAL_FIFO_TX_SIZE, SERIAL_FIFO_RX_SIZE);

#define SERIAL_BUFF_TX_SIZE 1
#define SERIAL_BUFF_RX_SIZE 1

NRF_SERIAL_BUFFERS_DEF(serial_buffs, SERIAL_BUFF_TX_SIZE, SERIAL_BUFF_RX_SIZE);

NRF_SERIAL_CONFIG_DEF(serial_config, NRF_SERIAL_MODE_POLLING,
    NULL, NULL, NULL, NULL);
//   &serial_queues, &serial_buffs, NULL, sleep_handler);

NRF_SERIAL_UART_DEF(serial_uart, 0);

//PPOS
#define STX 0x02
#define ACK 0x06

/**@brief Function for receiving Initialization package 0x74.
 */
void receiveSQInitPackage(void) {
  ret_code_t ret; // Return value of the nrf_serial_read function
  uint8_t cnt = 0;
  //static char responseArray[35] = {0};
  char BCC[] = {STX};
  static char BCCbyte[] = {0x14};
  char ACKbyte[] = {ACK};
  char uart_buf[35]; // Read UART buffer

  while (true) {
    char c; // Read UART character
    ret = nrf_serial_read(&serial_uart, &c, sizeof(c), NULL, NRF_SERIAL_MAX_TIMEOUT);
    APP_ERROR_CHECK(ret);
    uart_buf[cnt++] = c;
    if (c == BCCbyte) {
      cnt = 0;
    }
  }
  ret = nrf_serial_write(&serial_uart, ACKbyte, sizeof(ACKbyte), NULL, NRF_SERIAL_MAX_TIMEOUT); //end of sequence ACK
  (void)nrf_serial_flush(&serial_uart, 0);
  APP_ERROR_CHECK(ret);

} //end

int main(void) {
  ret_code_t ret;
  //PPOS
  uint8_t n, i = 0;
  static char STXbyte[] = {STX};
  static char commandArray[] = {0x09, 0x73, 0x00, 0x00, 0x00, 0x02, 0x01, 0x10, 0x00, 0x02};
  char BCC[] = {STX};
  static char BCCbyte[] = {0x69};

  ret = nrf_drv_clock_init();
  APP_ERROR_CHECK(ret);
  ret = nrf_drv_power_init(NULL);
  APP_ERROR_CHECK(ret);

  nrf_drv_clock_lfclk_request(NULL);
  ret = app_timer_init();
  APP_ERROR_CHECK(ret);

  // Initialize LEDs and buttons.
  bsp_board_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS);

  ret = nrf_serial_init(&serial_uart, &m_uart0_drv_config, &serial_config);
  APP_ERROR_CHECK(ret);

  ret = nrf_serial_write(&serial_uart, STXbyte, sizeof(STXbyte), NULL, NRF_SERIAL_MAX_TIMEOUT);
  APP_ERROR_CHECK(ret);
  ret = nrf_serial_write(&serial_uart,
      commandArray,
      commandArray[0] + 1, //length = 0x09 + 1
      NULL,
      NRF_SERIAL_MAX_TIMEOUT);
  APP_ERROR_CHECK(ret);
  for (i = 0; i <= 9; i++) {
    BCC[i] = BCC[i] ^ commandArray[i];
    if (i == 9) {
      sprintf(BCCbyte, "%c", BCC[i]);
      //printf("0x%02x ", BCC[i]); //debugger
    }
  } //end for 2
  ret = nrf_serial_write(&serial_uart, BCCbyte, sizeof(BCCbyte), NULL, NRF_SERIAL_MAX_TIMEOUT);
  (void)nrf_serial_flush(&serial_uart, 0);
  APP_ERROR_CHECK(ret);

  receiveSQInitPackage();

} //end main

/** @} */

Parents
  • Hi,

    Are you inputting any data to the RX line of the UART? And if you are, have you checket the pin with a logic analyzer to see that it is actually input on the pin?

    Since you have set the timeout_ms parameter of nrf_serial_read to NRF_SERIAL_MAX_TIMEOUT, the call will block until the requested amount of bytes have been received.

    Best regards,
    Jørgen

  • Have you made sure you have configured the serial interface with the same pin number that the RX signal is applied to?

    Could you try debugging the application, to see exactly what line it is stuck on? Also please try stepping the code to see if it enters the UART driver and get some events in this.

  • I got it all figured out. Thank you.

    /**
     * Copyright (c) 2016 - 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 <stddef.h>
    #include <stdint.h>
    //PPOS
    #include <string.h>
    
    #include "app_timer.h"
    #include "nrf.h"
    #include "nrf_delay.h"
    #include "nrf_drv_clock.h"
    #include "nrf_drv_power.h"
    #include "nrf_gpio.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_serial.h"
    
    #include "app_error.h"
    #include "app_util.h"
    #include "boards.h"
    //PPOS
    #include "ppos_application.h"
    #include "zzsdk_config.h"
    
    /** @file
     * @defgroup nrf_serial_example main.c
     * @{
     * @ingroup nrf_serial_example
     * @brief Example of @ref nrf_serial usage. 
     *
     */
    
    #define OP_QUEUES_SIZE 3
    #define APP_TIMER_PRESCALER NRF_SERIAL_APP_TIMER_PRESCALER
    
    static void sleep_handler(void) {
      __WFE();
      __SEV();
      __WFE();
    }
    
    NRF_SERIAL_DRV_UART_CONFIG_DEF(m_uart0_drv_config,
        RX_PIN_NUMBER, TX_PIN_NUMBER,
        RTS_PIN_NUMBER, CTS_PIN_NUMBER,
        NRF_UART_HWFC_DISABLED,
        //NRF_UART_HWFC_ENABLED,
        NRF_UART_PARITY_EXCLUDED,
        //NRF_UART_BAUDRATE_115200,
        NRF_UART_BAUDRATE_9600,
        UART_DEFAULT_CONFIG_IRQ_PRIORITY);
    
    #define SERIAL_FIFO_TX_SIZE 32
    //#define SERIAL_FIFO_RX_SIZE 32
    #define SERIAL_FIFO_RX_SIZE 128
    
    NRF_SERIAL_QUEUES_DEF(serial_queues, SERIAL_FIFO_TX_SIZE, SERIAL_FIFO_RX_SIZE);
    
    #define SERIAL_BUFF_TX_SIZE 1
    #define SERIAL_BUFF_RX_SIZE 1
    
    NRF_SERIAL_BUFFERS_DEF(serial_buffs, SERIAL_BUFF_TX_SIZE, SERIAL_BUFF_RX_SIZE);
    
    NRF_SERIAL_CONFIG_DEF(serial_config, NRF_SERIAL_MODE_POLLING, NULL, NULL, NULL, NULL);
    //   &serial_queues, &serial_buffs, NULL, sleep_handler);
    
    NRF_SERIAL_UART_DEF(serial_uart, 0);
    
    //PPOS
    #define STX 0x02
    #define ACK 0x06
    
    size_t bytesRead = 0;
    
    int main(void) {
      ret_code_t ret;
      //PPOS
      static char commandArray[] = {0x02, 0x09, 0x73, 0x00, 0x00, 0x00, 0x02, 0x01, 0x10, 0x00, 0x02, 0x69};
      uint8_t statusRequestArray[] = {0x06, 0x02, 0x01, 0x70, 0x73};
      uint8_t vendPriceArray[] = {0x06, 0x02, 0x0a, 0x72, 0x39, 0x39, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7a};
      uint8_t initResponseBuf[64] = {0};
      uint8_t machineStatusBuf[64] = {0};
      uint8_t ACKbyte[4] = {0};
    
      ret = nrf_drv_clock_init();
      APP_ERROR_CHECK(ret);
      ret = nrf_drv_power_init(NULL);
      APP_ERROR_CHECK(ret);
    
      nrf_drv_clock_lfclk_request(NULL);
      ret = app_timer_init();
      APP_ERROR_CHECK(ret);
    
      // Initialize LEDs and buttons.
      bsp_board_init(BSP_INIT_LEDS | BSP_INIT_BUTTONS);
      // Initialize serial
      ret = nrf_serial_init(&serial_uart, &m_uart0_drv_config, &serial_config);
      APP_ERROR_CHECK(ret);
      //send 0x73
      ret = nrf_serial_write(&serial_uart, commandArray, 12, NULL, 0);
      APP_ERROR_CHECK(ret);
      //receive 0x74
      ret = nrf_serial_read(&serial_uart, &initResponseBuf[0], 35, &bytesRead, 60);
      APP_ERROR_CHECK(ret);
      //send 0x70
      ret = nrf_serial_write(&serial_uart, &statusRequestArray[0], 5, NULL, 0);
      APP_ERROR_CHECK(ret);
      //receive 0x71
      ret = nrf_serial_read(&serial_uart, &machineStatusBuf[0], 30, &bytesRead, 55);
      APP_ERROR_CHECK(ret);
      //send 0x72
      ret = nrf_serial_write(&serial_uart, &vendPriceArray[0], 14, NULL, 0);
      APP_ERROR_CHECK(ret);
      //receive ACK
      ret = nrf_serial_read(&serial_uart, &ACKbyte[0], 1, &bytesRead, 5);
      APP_ERROR_CHECK(ret);
     
      /**
      @brief  Main forever loop for the application
      */
      /* Toggle LEDs. */
      while (true) {
        for (int i = 0; i < LEDS_NUMBER; i++) {
          bsp_board_led_invert(i);
    
          ret = nrf_serial_write(&serial_uart, &statusRequestArray[0], 5, NULL, 0);
          APP_ERROR_CHECK(ret);
    
          ret = nrf_serial_read(&serial_uart, &machineStatusBuf[0], 30, &bytesRead, 55);
          APP_ERROR_CHECK(ret);
    
          ret = nrf_serial_write(&serial_uart, &vendPriceArray[0], 14, NULL, 0);
          APP_ERROR_CHECK(ret);
    
          ret = nrf_serial_read(&serial_uart, &ACKbyte[0], 1, &bytesRead, 5);
          APP_ERROR_CHECK(ret);
    
          nrf_delay_ms(450);
        }
      }  
    
    } //end main
    
    /** @} */

  • Initially, I was unsure of how to use the serial read function since the documentation was unclear but eventually I figured it out. Sabine

Reply Children
No Data
Related