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

Serial port on the nRF52840 Dongle

Hi I am trying to init the serial on the nRF52840 Dongle but there are some defines missing in the boards/pca10069.h

I run this on the nRF52840 DK and it works fine.

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_ENABLED, NRF_UART_PARITY_EXCLUDED,
    NRF_UART_BAUDRATE_115200,
    UART_DEFAULT_CONFIG_IRQ_PRIORITY);

file: boards/pca10056.h

#define RX_PIN_NUMBER  8
#define TX_PIN_NUMBER  6
#define CTS_PIN_NUMBER 7
#define RTS_PIN_NUMBER 5
#define HWFC           true

Parents
  • Hi,

    There is no UART to USB bridge on the nRF52840 Dongle (the Segger debugger chip is used for that on the Development Kits), and therefore there is no default UART pins. 

    You can use any pins for the UART peripheral, but it is recommended to stay away from the pins marked "low frequency I/O only" in the ball assignment documentation.

    Also make sure that you choose some pins that is not used by other peripherals/components on the dongle, for instance P0.06 and P0.08 is used for LEDs.

    If you are communicating with a PC, you can also setup the dongle with USB CDC ACM to send data through virtual USB COM port. There is an example available in the SDK.

    Best regards,
    Jørgen

  • Hi,

    I'm interested in doing something similar to the original question here with an nRF52840 Dongle where I'd like to stream data over the dongle's USB connection and read it from a computer via /dev/ttyACMx. I've tried to compile the usbd_cdc_acm example to use as a template but it seems to rely on TX_PIN_NUMBER and RX_PIN_NUMBER constants that aren't defined for pca10059.

    Is this kind of setup possible with pca10059? Is usbd_cdc_acm the right example to use (it doesn't have a pca10059 subfolder)?

  • This works for both my dev board and the dongle.

    #include <stdlib.h>
    
    #include "zboss_api.h"
    #include "sdk_config.h"
    
    #include "app_usbd.h"
    #include "app_usbd_cdc_acm.h"
    #include "app_usbd_serial_num.h"
    //#include "app_usbd_string_desc.h"
    
    #include "boards.h"
    #include "serial_handler.h"
    
    /**
     * @brief Enable power USB detection
     *
     * Configure if example supports USB port connection
     */
    #ifndef USBD_POWER_DETECTION
    #define USBD_POWER_DETECTION true
    #endif
    
    static zb_uint8_t tx = 0;
    
    static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst, app_usbd_cdc_acm_user_event_t event);
    static void usbd_user_ev_handler(app_usbd_event_type_t event);
    
    #define CDC_ACM_COMM_INTERFACE  0
    #define CDC_ACM_COMM_EPIN       NRF_DRV_USBD_EPIN2
    
    #define CDC_ACM_DATA_INTERFACE  1
    #define CDC_ACM_DATA_EPIN       NRF_DRV_USBD_EPIN1
    #define CDC_ACM_DATA_EPOUT      NRF_DRV_USBD_EPOUT1
    
    
    /**
     * @brief CDC_ACM class instance
     * */
    APP_USBD_CDC_ACM_GLOBAL_DEF(serial_uart,
                                cdc_acm_user_ev_handler,
                                CDC_ACM_COMM_INTERFACE,
                                CDC_ACM_DATA_INTERFACE,
                                CDC_ACM_COMM_EPIN,
                                CDC_ACM_DATA_EPIN,
                                CDC_ACM_DATA_EPOUT,
                                //APP_USBD_CDC_COMM_PROTOCOL_AT_V250
                                APP_USBD_CDC_COMM_PROTOCOL_NONE
    );
    
    void serial_reset()
    {
        serial_command_hdr_t rts;
        rts.size    = 0xC0C0;
        rts.command = SERIAL_CMD_INVALID;
        app_usbd_cdc_acm_write(&serial_uart, &rts, sizeof(rts) );
    }
    
    void serial_init()
    {
        static const app_usbd_config_t usbd_config = {
            .ev_state_proc = usbd_user_ev_handler
        };
    
        ret_code_t ret;
    
        app_usbd_serial_num_generate();
    
        ret = app_usbd_init(&usbd_config);
        APP_ERROR_CHECK(ret);
    
        app_usbd_class_inst_t const * class_cdc_acm = app_usbd_cdc_acm_class_inst_get(&serial_uart);
        ret = app_usbd_class_append(class_cdc_acm);
        APP_ERROR_CHECK(ret);
    
        EVT_LOG("USBD CDC ACM example started.\n", NULL);
        if (USBD_POWER_DETECTION)
        {
            ret = app_usbd_power_events_enable();
            APP_ERROR_CHECK(ret);
        }
        else
        {
            EVT_LOG("No USB power detection enabled\nStarting USB now\n", NULL);
    
            app_usbd_enable();
            app_usbd_start();
        }
    }
    
    struct _tx_item
    {
        void* p;
        size_t s;
    };
    
    #define TX_MAX 32
    
    static int _tx_pos  = 0;
    static int _tx_next = 0;
    static struct _tx_item tx_queue[ TX_MAX ];
    
    static void __send_it(void* hdr, size_t hdr_size, void* buf, size_t blen )
    {
        zb_uint8_t* t = (zb_uint8_t*)malloc(hdr_size + blen );
        memcpy( t, hdr, hdr_size);
        if( blen > 0 && buf != NULL )
        {
            memcpy( &t[hdr_size], buf, blen );
        }
    
        if (tx_queue[_tx_next].p != NULL) 
        {
            // OOM.....
            PRINT("tx_queue is full !!... dropping packet! %d %d\n",  _tx_pos, _tx_next);
            free(t);
            return;
        }
        tx_queue[_tx_next].p = t;
        tx_queue[_tx_next].s = hdr_size + blen;    
    
        // No on going item send now!
        if( _tx_pos == _tx_next )
        {    
            if( app_usbd_cdc_acm_write(&serial_uart, t, hdr_size + blen ) == NRF_ERROR_INVALID_STATE )
            {           
                // No serial connected, just drop packet!
                tx_queue[_tx_next].p = NULL;
                tx_queue[_tx_next].s = 0;
                free(t);
                return;
            }
        }
        ++_tx_next;
        if( _tx_next >= TX_MAX )
        {
            _tx_next = 0;
        }
    }
    
    
    static cb_command_handler      command_handler     = NULL;
    static cb_port_status_handler  port_status_handler = NULL;
    
    void serial_set_command_handler(cb_command_handler cb)
    {
        command_handler = cb;
    }
    
    void serial_set_port_status_handler(cb_port_status_handler cb)
    {
        port_status_handler = cb;
    }
    
    
    static void cdc_acm_user_ev_handler(app_usbd_class_inst_t const * p_inst, app_usbd_cdc_acm_user_event_t event)
    {
        app_usbd_cdc_acm_t const * p_cdc_acm = app_usbd_cdc_acm_class_get(p_inst);
    
        static char tmp[1024];
        static uint16_t tmp_i     = 0;
        static uint16_t size      = 0;
    
        switch (event)
        {
            case APP_USBD_CDC_ACM_USER_EVT_PORT_OPEN:
            {        
                tmp_i = 2;
                size  = 0;
                tx = 0;
                memset(tmp,0,sizeof(tmp));
                /*Setup first transfer*/
                ret_code_t ret = app_usbd_cdc_acm_read(&serial_uart,
                                                       tmp,
                                                       sizeof(size));
            
                UNUSED_VARIABLE(ret);
                bsp_board_led_on(BSP_BOARD_LED_0);
                if( port_status_handler != NULL ) 
                {
                    port_status_handler( true );
                }
                break;
            }
            case APP_USBD_CDC_ACM_USER_EVT_PORT_CLOSE:
                bsp_board_led_off(BSP_BOARD_LED_0);
                if( port_status_handler != NULL ) 
                {
                    port_status_handler( false );
                }
                break;
            case APP_USBD_CDC_ACM_USER_EVT_TX_DONE:
                free( tx_queue[_tx_pos].p );
                tx_queue[_tx_pos].p = NULL;
                tx_queue[_tx_pos].s = 0;
    
                // We should normaly only go once in this loop, but if there is an
                // error sending its most likly due to disconnected serial and we will
                // loop thrue and flush the queue.
                do
                {
                    ++_tx_pos;
                    if( _tx_pos >= TX_MAX )
                    {
                        _tx_pos = 0;
                    }
                
                    if( _tx_pos != _tx_next )
                    {
                        if( app_usbd_cdc_acm_write(&serial_uart, tx_queue[_tx_pos].p, tx_queue[_tx_pos].s ) == NRF_ERROR_INVALID_STATE )
                        {           
                            PRINT( "Drop from queue packet... %d %d\n", _tx_pos, _tx_next);
                            free(tx_queue[_tx_pos].p);
                            tx_queue[_tx_pos].p = NULL;
                            tx_queue[_tx_pos].s = 0;                        
                        }
                        else
                        {
                            break;
                        }
                     }
                }while( _tx_pos != _tx_next );
    
                break;
            case APP_USBD_CDC_ACM_USER_EVT_RX_DONE:
            {           
                ret_code_t ret;   
                do
                { 
                    //size_t xsize = app_usbd_cdc_acm_rx_size(p_cdc_acm);
                    //EVT_LOG("Bytes waiting: %zd %hu:%hu\n", xsize, tmp_i, size );
                    if( size == 0 )
                    {
                        memcpy(&size, tmp, sizeof(size));
                        ret = app_usbd_cdc_acm_read_any(&serial_uart, &tmp[tmp_i], 1);
                        continue;
                    }
                    if (tmp_i < size) 
                    {
                        ++tmp_i;
                    }
                    if (size == tmp_i) 
                    {
                        if (command_handler != NULL) 
                        {
                            command_handler(tmp);
                        }
    
                        tmp_i = 2;
                        size  = 0;
                        memset(tmp,0,sizeof(tmp));
                        app_usbd_cdc_acm_read(&serial_uart, tmp, sizeof(size));
                        break;
                    }
                    ret = app_usbd_cdc_acm_read_any(&serial_uart, &tmp[tmp_i], 1);
                    if (ret != NRF_SUCCESS) 
                    {
                        break;
                    }
                } while (ret == NRF_SUCCESS);
                break;
            }
            default:
                PRINT("Unhandled usb event: %x\n",event);
                break;
        }
    }
    
    static void usbd_user_ev_handler(app_usbd_event_type_t event)
    {
        switch (event)
        {
            case APP_USBD_EVT_DRV_SUSPEND:
                PRINT("USB_RESUME\n",NULL);
                break;
            case APP_USBD_EVT_DRV_RESUME:
                PRINT("USB_RESUME\n",NULL);
                break;
            case APP_USBD_EVT_STARTED:
                break;
            case APP_USBD_EVT_STOPPED:
                app_usbd_disable();
                bsp_board_leds_off();
                break;
            case APP_USBD_EVT_POWER_DETECTED:
                PRINT("USB power detected\n",NULL);
    
                if (!nrf_drv_usbd_is_enabled())
                {
                    app_usbd_enable();
                }
                break;
            case APP_USBD_EVT_POWER_REMOVED:
                PRINT("USB power removed\n",NULL);
                app_usbd_stop();
                break;
            case APP_USBD_EVT_POWER_READY:
                PRINT("USB ready\n",NULL);
                app_usbd_start();
                break;
            default:
                PRINT("USB unhandled event:%x\n", event);
                break;
        }
    }
    
    void serial_process()
    {
        app_usbd_event_queue_process();
    }

  • Hey Jimmy,

    I'm trying to run this sample on a nr52840 dongle, and I can't seem to find a definition for the rts struct. Any chance you'd know?

  • The struct is not part of Nordic SDK its part of our source. 

    typedef struct serial_command_hdr
    {
        zb_uint16_t size;
        zb_uint8_t command; // serial_command_t
    } serial_command_hdr_t;

  • Running into something similar on the cb_command_handler/cb_port_status_handler. If this is part of a larger framework, let me know.

  • typedef void (*cb_command_handler)(char*);
    void serial_set_command_handler(cb_command_handler cb);
    typedef void (*cb_port_status_handler)(bool);
    void serial_set_port_status_handler(cb_port_status_handler cb);

    -----

    void handle_serial_command(char *tmp)
    {
        serial_command_hdr_t *hdr = (serial_command_hdr_t *)tmp;

Reply Children
No Data
Related