Posted 2017-09-29 11:51:52 +0200

blogs->all

Multiple channels in RTT

    No tags

Segger RTT (Real-Time Terminal) supports multiple data channels.

RTT Viewer uses channel 0 only, and implements multiple virtual terminals on top of this. The terminal can be switched by SEGGER_RTT_SetTerminal(). Channel 0 is used by NRF_LOG. NRF_LOG does not do terminal switching, so you can do it yourself (be careful about reentracy though).

Data from other channels can be read using RTT Logger. To send data from NRF to RTT Logger:

  1. In sdk_config.h, adjust value of SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS. The default is 2, which gives you 1 extra channel besides channel 0. In the example below, it should be set to 3.
  1. Allocate data buffer (on heap!) for each channel

     uint8_t *data1Buffer[128];
     uint8_t *data2Buffer[128];
    
  2. Call SEGGER_RTT_Init() or let NRF_LOG_INIT() do it for you if you have configured logging via RTT.

  3. Call SEGGER_RTT_ConfigUpBuffer() to tell RTT to use your buffers.

     SEGGER_RTT_ConfigUpBuffer(1, "DATA1", data1Buffer, 128, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
     SEGGER_RTT_ConfigUpBuffer(2, "DATA2", data2Buffer, 128, SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL);
    
  4. Call SEGGER_RTT_Write(), SEGGER_RTT_WriteString() or SEGGER_printf() specifying your channel number.

     int cnt = 0;
     char buf[32];
     while (1) {    
             for (int j=0; j<3; j++) {
                     sprintf(buf, "Message # %d channel %d\n", cnt, j);
                     SEGGER_RTT_WriteString(j, buf);
             }
             cnt++;
             nrf_delay_ms(2000);
     }
    
  1. Start RTT Logger and let the magic happen: https://i.imgur.com/GDNgoCM.png Note that by default RTT Logger creates log files in the same directory as its exe file.

  2. Detailed documentation for SEGGERRTT* functions can be found in chapter 13 of J-Link user manual.

  3. You can also use down buffers to send data to NRF. However, there is no host-side software to do this, except for sending data to channel 0 via RTT Viewer. But apparently you can do it yourself if you buy J-Link SDK license.

4 comments

koczis gravatar image

Posted Oct. 10, 2017, 3:51 p.m.

Hello,

I did it exactly as you, but I'm having problems with data reception. It appears that I can't use more than one RTT listening application (no matter: Viewer, Client, Logger) to save proper data. When I try, either only one channel is actually receiving anything or data get corrupted. So, I can't seem to achieve what you present on your screenshot. Have you perhaps changed anything else in your RTT lib config?

Posted Oct. 12, 2017, 2:42 p.m.

No, the RTT libs are from clean SDK14. Did you call SEGGER_RTT_Init()?

Here's how I use it now, for reference. (You need to provide _ASSERT macro).

#include <string.h>
#include "SEGGER_RTT.h"
#include "RTT_data.h"
#include "sdk_config.h"

#define RTT_DATA_BUFFER_SIZE             128                    // FIFO size
#define RTT_DATA_CHANNEL                 1                    // RTT channel number (RTT Viewer and NRF_LOG use 0)
#define RTT_DATA_USE_BLOCKING_MODE         1                    // Block if not enough space in FIFO
#define RTT_DATA_ASSERT_ON_OVERFLOW     0                    // If RTT_DATA_USE_BLOCKING_MODE is 0, assert if not enough space in the FIFO


uint8_t RTT_buffer[RTT_DATA_BUFFER_SIZE];

bool RTT_initialized = false;

void RTT_data_init(void)
{
#if (RTT_DATA_CHANNEL > SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS-1)
#error "Please increase SEGGER_RTT_CONFIG_MAX_NUM_UP_BUFFERS in sdk_config.h"
#endif

#if NRF_LOG_BACKEND_RTT_ENABLED
    // NRF_LOG will initialize RTT for us
#else
    SEGGER_RTT_Init();
#endif

#if RTT_DATA_USE_BLOCKING_MODE
    int mode = SEGGER_RTT_MODE_BLOCK_IF_FIFO_FULL;
#else
    int mode = SEGGER_RTT_MODE_NO_BLOCK_SKIP;
#endif

    int ret = SEGGER_RTT_ConfigUpBuffer(RTT_DATA_CHANNEL, "RTT_DATA", RTT_buffer, RTT_DATA_BUFFER_SIZE, mode);
    _ASSERT(ret>=0);
    RTT_initialized = true;
}

void RTT_data_send(uint8_t *data, int size)
{
    _ASSERT(RTT_initialized);
    int ret = SEGGER_RTT_Write(RTT_DATA_CHANNEL, data, size);
#if RTT_DATA_ASSERT_ON_OVERFLOW
    _ASSERT(ret == size);
#endif
}

void RTT_data_send_string(char *string)
{
    _ASSERT(RTT_initialized);
    int ret = SEGGER_RTT_WriteString(RTT_DATA_CHANNEL, string);
#if RTT_DATA_ASSERT_ON_OVERFLOW
    _ASSERT(ret == strlen(string));
#endif
}
koczis gravatar image

Posted Oct. 12, 2017, 8:19 p.m.

Yes, I call SEGGER_RTT_Init. I do everything exactly as you, except I have 2 additional channels - 3 in all. I wonder whether the buffers shouldn't be placed like they are for channel 0 in "SEGGER_RTT.h":

SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acUpBuffer  [BUFFER_SIZE_UP]));
SEGGER_RTT_PUT_BUFFER_SECTION(SEGGER_RTT_BUFFER_ALIGN(static char _acDownBuffer[BUFFER_SIZE_DOWN]));

Posted Oct. 21, 2017, 3:38 p.m.

Hi,

You use:

uint8_t *data1Buffer[128];
uint8_t *data2Buffer[128];

...and state that this is on the heap. This allocates 128 pointers to uint8_t twice, so 1 KB of memory. You either need a plain pointer (kill the array) and use the equivalent of "malloc" or just remove the * and use a plain array.

Short: this is not a pointer to an array of 128 bytes.

Sign in to comment.

User menu

    or sign up

Recent questions

Related posts by tag

No results