AnsweredAssumed Answered

FILE stream for ITM redirect

Question asked by Mate Rigo on Apr 1, 2014
Hi everyone!

My question is in short: how can I set up a FILE stream for using it like the stdout and stderr to with the ITM trace facility.


My question explained in more detail:

My system:
MCU: STM32F103RB
Debugger: Segger Jlink
IDE: Eclipse Kepler + GNU ARM Eclipse plugin
Toolchain: GNU Tools for ARM Embedded Processors + make and rm from Codesourcery Lite

I've setup a project in eclipse using the Gnu Arm Eclipse plugin. I used the following project example: STM32F10x StdPeripher C/C++ Project
I used retargetting for system calls, which uses the libnosys.a.

The example comes with a _write implementation, which in turns calls a _write_trace_implementaion. I modified both of them, so they don't use the ITM0 channel, but the channel in accordance of the FILE stream used for the call.
The fprintf apparently passes the stdout->_file value to the first parameter of the _write function.
int
_write(int fd, char* ptr, int len)
{
#if defined(DEBUG)
 
#if defined(INCLUDE_TRACE_ITM)
      return _write_trace_itm(fd, ptr, len);
#elif defined(INCLUDE_TRACE_SEMIHOSTING_STDOUT)
      return _write_trace_semihosting_stdout(ptr, len);
#elif defined(INCLUDE_TRACE_SEMIHOSTING_DEBUG)
      return _write_trace_semihosting_debug(ptr, len);
#else
#warning "no trace implementation"
#endif
 
#endif // DEBUG
 
  return -1;
}

int
_write_trace_itm(int fd, char* ptr, int len)
{
  static int isInitialised;
  if (isInitialised == 0) {
 
      // TODO: enable SWO
      // For the SEGGER J-Link GDB server, this is not required...
 
      ITM->TER = 0xFF; //Enable every ITM channel
      isInitialised = 1;
  }
 
  // Use Stimulus port channel 0
  int i = 0;
  for (; i < len; i++)
    {
 
      // Check if ITM_TCR.ITMENA is set
      if ((ITM_TCR & 1) == 0)
        {
          return i; // return the number of sent characters (may be 0)
        }
 
      // Check if stimulus port 0 is enabled
      if ((ITM_ENA & 1) == 0)
        {
          return i; // return the number of sent characters (may be 0)
        }
 
      // Wait until STIMx is ready,
      while ((ITM->PORT[fd].u8 & 1) == 0)
        ;
      // then send data
      ITM->PORT[fd].u8 = *ptr++;
 
    }
 
  return len; // all characters successfully sent
}

During debugging, I can see, that calling
fprintf(stdout, "hello\n");
passes the value to fd==1 my write trace implementation
_write_trace_itm(int fd, char* ptr, int len)
This is then put to the ITM1 channel, which I can see in the Segger's SWO viewer program.

Whereas calling 
fprintf(stderr, "hello\n");
passes fd==2 to the trace writer.

This is all very cool, as I can have a different channel for different events, like standard messages, and error messages :)

Now I'd like to set up another stream writer, that would lets say use the channel 3, and so on.

How do I set up one of these in this environment, or in any ARM environment?

I do know, that in AVR world, I would do something like this:
FILE uart_output = FDEV_SETUP_STREAM(uart_putchar, NULL, _FDEV_SETUP_WRITE);
See here
But this obviously does not work here, nor have I found anything similar.

The goal is to have multiple FILE stream writers besides the stdout and stderr, which I can redirect to the ITM output.

Any insight on this would be appreciated.
Attached you will find the project mentioned.

BTW: my backup plan is to just do my own implementation of sendchar, and buffers, which would be handled by a low priority task, just thought I'd give this a try.

Attachments

Outcomes