cancel
Showing results for 
Search instead for 
Did you mean: 

FILE stream for ITM redirect

rigomate2
Associate III
Posted on April 01, 2014 at 14:00

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 +

http://gnuarmeclipse.livius.net/

Toolchain:

https://launchpad.net/gcc-arm-embedded

+ make and rm from

http://www.mentor.com/embedded-software/codesourcery

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);

http://www.appelsiini.net/2011/simple-usart-with-avr-libc

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. #printf-fprintf-itm
0 REPLIES 0