2014-04-01 05:00 AM
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 fromhttp://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);
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