diff --git a/CHANGES.md b/CHANGES.md index d345fce9..a27bdca4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,15 @@ Version 2.3.0 In progress +* Modify orblcd to receive shorter messages than word-length (if appropriate) +* Extend from-target timestamping to 1/10th microsecond resolution with rounding * Add support for ITM rollover counters in orbtop (if they deliver information, they will be displayed) * Add STM32 CORTEX-M33 support (Tested on STM32U5A5) +* Add communications pacing to orbtop for direct file reads +* Remove memory leak from orbtop +* Remove reference ro TPIU and ETM LAR's...they don't exist (per #156) +* Remove redundant access to DBGMCU on SAMD5 per #$157 +* Fix legacy port reflection when monitoring is not switched on it orbuculum +* Fixup bug in _processFunctionDie & other loadelf fixes +* Improve demangling of C++ names 21st Sept 2024 (Version 2.2.0) diff --git a/Docs/BlackMagicProbe-Interface b/Docs/BlackMagicProbe-Interface index 11920f49..8a483d9a 100644 --- a/Docs/BlackMagicProbe-Interface +++ b/Docs/BlackMagicProbe-Interface @@ -4,10 +4,7 @@ Using the Black Magic Debug Probe When connecting to a Black Magic Debug probe the command line for Orbuculum will be something like; ->./orbuculum -b swo/ -c 0,text,c - -...which will create the fifo 'text' in a subdirectory swo of the current -directory, delivering SWO channel 0. The directory must exist already. +>./orbuculum -m 500 By default on BMP the SWO baudrate is 2.25MBps but that can be changed as an optional parameter to the monitor traceswo command at the gdb diff --git a/Inc/generics.h b/Inc/generics.h index becbea74..1a7ff3e4 100644 --- a/Inc/generics.h +++ b/Inc/generics.h @@ -12,6 +12,7 @@ #include #include #include +#include #include #define EOL "\n" @@ -98,7 +99,7 @@ char *genericsUnescape( char *str ); uint64_t genericsTimestampuS( void ); uint32_t genericsTimestampmS( void ); bool genericsSetReportLevel( enum verbLevel lset ); -void genericsPrintf( const char *fmt, ... ); +void genericsFPrintf( FILE *stream, const char *fmt, ... ); char *genericsGetBaseDirectory( void ); const char *genericsBasename( const char *n ); const char *genericsBasenameN( const char *n, int c ); diff --git a/Inc/orblcd_protocol.h b/Inc/orblcd_protocol.h index 30fa8081..d0b5fd49 100644 --- a/Inc/orblcd_protocol.h +++ b/Inc/orblcd_protocol.h @@ -14,19 +14,24 @@ #define ORBLCD_CMD_CLEAR (3) #define ORBLCD_CMD_GOTOXY (4) +#define LCD_BE (0) +#define LCD_LE (1) + #define ORBLCD_ENCODE_X(x) ((x&0xfff)<<0) #define ORBLCD_ENCODE_Y(x) ((x&0xfff)<<12) #define ORBLCD_ENCODE_D(x) ((x&0x03)<<24) #define ORBLCD_ENCODE_C(x) ((x&0x3f)<<26) +#define ORBLCD_ENCODE_L(x) ((x&0x01)<<31) #define ORBLCD_DECODE_X(x) ((x>>0)&0xfff) #define ORBLCD_DECODE_Y(x) ((x>>12)&0xfff) #define ORBLCD_DECODE_D(x) ((x>>24)&0x03) -#define ORBLCD_DECODE_C(x) ((x>>26)&0x3f) +#define ORBLCD_DECODE_C(x) ((x>>26)&0x1f) +#define ORBLCD_DECODE_L(x) ((x>>31)&0x01) #define ORBLCD_GET_DEPTH(x) (((int[]){1,8,16,24})[ORBLCD_DECODE_D(x)]) #define ORBLCD_PIXELS_PER_WORD(x) (((int[]){32,4,2,1})[ORBLCD_DECODE_D(x)]) -#define ORBLCD_OPEN_SCREEN(x,y,d) (ORBLCD_ENCODE_C(ORBLCD_CMD_INIT_LCD)|ORBLCD_ENCODE_D(d)|ORBLCD_ENCODE_X(x)|ORBLCD_ENCODE_Y(y)) +#define ORBLCD_OPEN_SCREEN(x,y,d,l) (ORBLCD_ENCODE_L(l)|ORBLCD_ENCODE_C(ORBLCD_CMD_INIT_LCD)|ORBLCD_ENCODE_D(d)|ORBLCD_ENCODE_X(x)|ORBLCD_ENCODE_Y(y)) #define ORBLCD_CLOSE_SCREEN (ORBLCD_ENCODE_C(ORBLCD_CMD_CLOSE_SCREEN)) #define ORBLCD_CLEAR (ORBLCD_ENCODE_C(ORBLCD_CMD_CLEAR)) diff --git a/Inc/symbols.h b/Inc/symbols.h index 19aa5548..1f3dd016 100644 --- a/Inc/symbols.h +++ b/Inc/symbols.h @@ -26,11 +26,11 @@ extern "C" { #define NO_FUNCTION 0xffffffff /* No function defined */ #define NO_DESTADDRESS 0xffffffe0 /* No address defined */ -#define SPECIALS_MASK 0xfffffff0 -#define FN_SLEEPING (SPECIALS_MASK|0xb) /* Marker for sleeping case */ +#define SPECIALS_MASK 0xffffff80 +#define FN_SLEEPING (SPECIALS_MASK|0xfb) /* Marker for sleeping case */ #define FN_SLEEPING_STR "** Sleeping **" /* String for sleeping case */ -#define INTERRUPT (SPECIALS_MASK|0xd) +#define INTERRUPT (SPECIALS_MASK|0xfd) #define FN_INTERRUPT_STR "INTERRUPT" enum symbolErr { SYMBOL_OK, SYMBOL_NOELF, SYMBOL_NOOBJDUMP, SYMBOL_UNSPECIFIED }; diff --git a/README.md b/README.md index d22a58e2..cccb5d64 100644 --- a/README.md +++ b/README.md @@ -45,8 +45,6 @@ used as a base interface to the target by other programs in the suite. Generally this for the TRACE tool you're using and then you can just leave it running. It will grab data from the target and make it available to clients whenever it can. -* orbfifo: The fifo pump: Turns a trace feed into a set of fifos or, optionally, permanent files. - * orbcat: A simple cat utility for ITM channel data. * orbdump: A utility for dumping raw SWO data to a file for post-processing. @@ -245,12 +243,21 @@ Building on Linux Dependencies ------------ * libusb-1.0 -* libczmq-dev -* ncurses -* libsdl +* cmake +* pkg-config +* libczmq5-dev +* ncurses-dev +* libsdl2-dev +* libzstd-dev * libelf-dev * libcapstone-dev +On Debian 12, at least, the following command should get you everything you need; + +``` +sudo apt-get install libusb-1.0-0-dev cmake pkg-config libczmq5-dev ncurses-dev libelf-dev libsdl2-dev libzstd-dev libcapstone-dev +``` + Build ----- @@ -275,7 +282,7 @@ A udev rules files is included in ```Support/60-orbcode.rules``` The default ins Building on OSX =============== -* `brew install libusb zmq sdl2` +* `brew install libusb zmq sdl2 libelf` If you are on an Intel Mac: @@ -412,7 +419,7 @@ probes are found you will get the option to choose between them. To avoid this c serial number for the probe you want to use on the command line. The command above will start the daemon with a monitor reporting interval of 100ms. Orbuculum exposes TCP ports 3402 and 3443 to which network clients can connect. 3402 delivers orbflow, 3443+x deliver raw frames. Both will relay to any -client that is connected (such as orbcat, orbfifo or orbtop). +client that is connected (such as orbcat or orbtop). The practical limit to the number of clients that can connect is set by the speed of the host machine....but there's nothing stopping you using another one on the local network :-) Orbuculum can optionally call out to `orbtrace` when a probe first connects. this is typically used to set configuration parameters for the problem. For example, if you've got an @@ -474,79 +481,6 @@ For `orbuculum`, the specific command line options of note are; `-t, --tag x,y,...`: List of streams to decode (and onward route) from the probe (low stream numbers are TPIU channels). *By default only stream 1 (ITM) is routed over legacy protocol, add additional streams via this command* - -Orbfifo -------- - -**Note:** `orbfifo` is not supported on Windows. Use `orbzmq` instead. - -The easiest way to use the output from orbuculum is with one of the utilities -such as `orbfifo`. This creates a set of fifos or permanent files in a given -directory containing the decoded streams which apps can exploit directly. It also has -a few other tricks up it's sleeve like filewriter capability. It used to be integrated into -`orbuculum` but seperating it out splits the trace interface from the user space utilities, this is a -Good Thing(tm). - -A typical command line would be; - -```>orbfifo -b swo/ -c 0,text,"%c" -v 1``` - -The directory 'swo/' is expected to already exist, into which will be placed -a file 'text' which delivers the output from swo channel 0 in character -format. Multiple -c options can be provided to set up fifos for individual channels -from the debug device. The format of the -c option is; - -```-c ChannelNum,ChannelName,FormatString``` - -ChannelNum is 0..31 and corresponds to the ITM channel. The name is the one -that will appear in the directory and the FormatString can present the data -using any printf-compatable formatting you prefer, so, the following are all -legal channel specifiers; - - -c 7,temperature,"%d \260C\n" - -c 2,hexAddress,"%08x," - -c 0,volume,"\l%d\b\n" - -Be aware that if you start making the formatting or screen handling too complex -its quite possible your machine might not keep up...and then the client will be dropped and you will loose data! - -While you've got `orbfifo` running a further fifo `hwevent` will be found in -the output directory, which reports on events from the hardware, one event per line as follows; - -* `0,[Status],[TS]` : Time status and timestamp. -* `1,[EventType],[ExceptionNumber]` : Hardware exception. Event type is one of [Enter, Exit, Resume]. -* `2,[PCAddr]` : Report Program Counter Sample. -* `3,[DWTEvent]` : Report on DWT event from the set [CPI,Exc,Sleep,LSU,Fold and Cyc]. -* `4,[Comp],[RW],[Data]` : Report Read/Write event. -* `5,[Comp],[Addr]` : Report data access watchpoint event. -* `6,[Comp],[Ofs]` : Report data offset event. -* `7` : Currently unused. -* `8,[Status],[Address]` : ISYNC event. - -The command line options are; - - `-b, --basedir [basedir]`: for channels, terminated with a trailing directory seperator, - so if you put xyz/chan then all ITM software channels will end up in a directory - xyz/chan. If xyz/chan doesn't exist, then channel creation will fail silently. - - `-c, --channel [Number],[Name],[Format]`: of channel to populate (repeat per channel) using printf formatting. - - `-E`: When reading from file, terminate when file exhausts, rather than waiting for more data to arrive. - - `-f, --input-file [filename]`: Take input from specified file (CTRL-C to abort from this). - - `-h, --help`: Brief help. - - `-P, --permanent`: Create permanent files rather than fifos - useful when you want to use the processed data later. - - `-s [address]:[port]`: Set address for Source connection, (default localhost:3443). - - `-t, --tag`: Which orbflow tag to use (normally 1). - - `-v, --verbose`: Verbose mode 0==Errors only, 1=Warnings (Default) 2=Info, 3=Full Debug. - - `-W, --writer-path [path]` : Enable filewriter functionality with output in specified directory (disabled by default). - Orbzmq ------ `orbzmq` is utility that connects to orbuculum over the network and outputs data from various ITM HW and SW channels that it finds. This output is sent over a [ZeroMQ](https://zeromq.org/) PUBLISH socket bound to the specified URL. Each published message is composed of two parts: **topic** and **payload**. Topic can be used by consumers to filter incoming messages, payload contains actual message data - for SW channels formatted or raw data and predefined format for HW channels. @@ -716,7 +650,8 @@ options for orbcat are; `-w, --window [string]`: Title for on-screen window. - + `-x, --exceptions`: Include exception information in output, in time order + Orbtop ------ diff --git a/Src/generics.c b/Src/generics.c index ae8843d7..9a71c253 100644 --- a/Src/generics.c +++ b/Src/generics.c @@ -338,7 +338,7 @@ char *genericsGetBaseDirectory( void ) #endif } // ==================================================================================================== -void genericsPrintf( const char *fmt, ... ) +void genericsFPrintf( FILE *stream, const char *fmt, ... ) /* Print to output stream */ @@ -355,7 +355,7 @@ void genericsPrintf( const char *fmt, ... ) { if ( *p != CMD_ALERT[0] ) { - putc( *p++, stderr ); + putc( *p++, stream ); } else { @@ -367,7 +367,7 @@ void genericsPrintf( const char *fmt, ... ) case 'a'...'f': if ( _screenHandling ) { - fprintf( stderr, CC_COLOUR, _htoi( *p ) > 7, _htoi( *p ) & 7 ); + fprintf( stream, CC_COLOUR, _htoi( *p ) > 7, _htoi( *p ) & 7 ); } p++; @@ -376,7 +376,7 @@ void genericsPrintf( const char *fmt, ... ) case 'u': if ( _screenHandling ) { - fprintf( stderr, CC_PREV_LN ); + fprintf( stream, CC_PREV_LN ); } p++; @@ -385,7 +385,7 @@ void genericsPrintf( const char *fmt, ... ) case 'U': if ( _screenHandling ) { - fprintf( stderr, CC_CLR_LN ); + fprintf( stream, CC_CLR_LN ); } p++; @@ -394,7 +394,7 @@ void genericsPrintf( const char *fmt, ... ) case 'r': if ( _screenHandling ) { - fprintf( stderr, CC_RES ); + fprintf( stream, CC_RES ); } p++; @@ -402,7 +402,7 @@ void genericsPrintf( const char *fmt, ... ) case 'z': /* We'll take a flyer on it being vt100 compatible */ - fprintf( stderr, CC_CLEAR_SCREEN ); + fprintf( stream, CC_CLEAR_SCREEN ); p++; break; @@ -412,7 +412,7 @@ void genericsPrintf( const char *fmt, ... ) } } - fflush( stdout ); + fflush( stream ); } // ==================================================================================================== void genericsReport( enum verbLevel l, const char *fmt, ... ) @@ -426,13 +426,13 @@ void genericsReport( enum verbLevel l, const char *fmt, ... ) if ( l <= lstore ) { fflush( stdout ); - genericsPrintf( colours[l] ); + genericsFPrintf( stderr, colours[l] ); va_list va; va_start( va, fmt ); vsnprintf( op, MAX_STRLEN, fmt, va ); va_end( va ); - genericsPrintf( "%s", op ); - genericsPrintf( C_RESET ); + genericsFPrintf( stderr, "%s", op ); + genericsFPrintf( stderr, C_RESET ); fflush( stderr ); } } @@ -447,9 +447,9 @@ void genericsExit( int status, const char *fmt, ... ) va_start( va, fmt ); vsnprintf( op, MAX_STRLEN, fmt, va ); va_end( va ); - genericsPrintf( C_VERB_ERROR ); - genericsPrintf( op ); - genericsPrintf( C_RESET ); + genericsFPrintf( stderr, C_VERB_ERROR ); + genericsFPrintf( stderr, op ); + genericsFPrintf( stderr, C_RESET ); fflush( stderr ); exit( status ); diff --git a/Src/itmfifos.c b/Src/itmfifos.c deleted file mode 100644 index d4de0f2d..00000000 --- a/Src/itmfifos.c +++ /dev/null @@ -1,835 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ -/* - * Fifo support - * ============ - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "git_version_info.h" -#include "generics.h" -#include "itmDecoder.h" -#include "oflow.h" -#include "fileWriter.h" -#include "itmfifos.h" -#include "msgDecoder.h" - -#ifndef O_BINARY - #define O_BINARY 0 -#endif - -#define MAX_STRING_LENGTH (100) /* Maximum length that will be output from a fifo for a single event */ - -struct runThreadParams /* Structure for parameters passed to a software task thread */ -{ - int portNo; - int listenHandle; - bool permafile; - struct Channel *c; -}; - -struct Channel /* Information for an individual channel */ -{ - char *chanName; /* Filename to be used for the fifo */ - char *presFormat; /* Format of data presentation to be used */ - - /* Runtime state */ - int handle; /* Handle to the fifo */ - pthread_t thread; /* Thread on which it's running */ - struct runThreadParams params; /* Parameters for running thread */ - char *fifoName; /* Constructed fifo name (from chanPath and name) */ - bool ending; /* Flag indicating its time to disappear */ -}; - -struct itmfifosHandle - -{ - /* The decoders and the packets from them */ - struct ITMDecoder i; - struct ITMPacket h; - struct OFLOW ot; - enum timeDelay timeStatus; /* Indicator of if this time is exact */ - uint64_t timeStamp; /* Latest received time */ - - /* Timestamp info */ - uint64_t lastHWExceptionTS; - - /* Configuration information */ - char *chanPath; /* Path to where to put the fifos */ - bool filewriter; /* Is the filewriter in use? */ - bool forceITMSync; /* Is ITM to be forced into sync? */ - bool permafile; /* Use permanent files rather than fifos */ - int tag; /* Which OFLOW stream are we decoding? */ - bool amEnding; /* Flag indicating end is in progress */ - - enum Prot protocol; /* What protocol to communicate (default to OFLOW (== orbuculum)) */ - - struct Channel c[NUM_CHANNELS + 1]; /* Output for each channel */ -}; - - -// ==================================================================================================== -// ==================================================================================================== -// ==================================================================================================== -// Private routines -// ==================================================================================================== -// ==================================================================================================== -// ==================================================================================================== - -// ==================================================================================================== -// Handlers for the fifos -// ==================================================================================================== -static void *_runFifo( void *arg ) - -/* This is the control loop for the channel fifos (for each software port) */ - -{ - struct runThreadParams *params = ( struct runThreadParams * )arg; - struct Channel *c = params->c; - struct swMsg m; - uint32_t w; - - char constructString[MAX_STRING_LENGTH]; - int opfile; - size_t readDataLen, writeDataLen, written = 0; - - assert( ¶ms->c->params == params ); - - /* Remove the file if it exists */ - unlink( c->fifoName ); - - if ( !params->permafile ) - { - /* This is a 'conventional' fifo, so it must be created */ - if ( mkfifo( c->fifoName, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) < 0 ) - { - pthread_exit( NULL ); - } - } - - do - { - /* Keep on opening the file (in case the fifo is opened/closed multiple times) */ - /* We use RDWR to allow the open to proceed without a remote end */ - - if ( !params->permafile ) - { - opfile = open( c->fifoName, O_RDWR | O_BINARY | O_NONBLOCK ); - } - else - { - opfile = open( c->fifoName, O_WRONLY | O_CREAT | O_BINARY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ); - } - - do - { - /* ....get the packet. This will hang here until a packet arrives or the link closes */ - readDataLen = read( params->listenHandle, &m, sizeof( struct swMsg ) ); - - if ( readDataLen < 0 ) - { - continue; - } - - if ( c->presFormat ) - { - // formatted output....start with specials - if ( strstr( c->presFormat, "%f" ) ) - { - /* type punning on same host, after correctly building 32bit val - * only unsafe on systems where u32/float have diff byte order */ - float *nastycast = ( float * )&m.value; - writeDataLen = snprintf( constructString, MAX_STRING_LENGTH, c->presFormat, *nastycast, *nastycast, *nastycast, *nastycast ); - } - else if ( strstr( c->presFormat, "%c" ) ) - { - /* Format contains %c, so execute repeatedly for all characters in sent data */ - writeDataLen = 0; - uint8_t op[4] = {m.value & 0xff, ( m.value >> 8 ) & 0xff, ( m.value >> 16 ) & 0xff, ( m.value >> 24 ) & 0xff}; - - uint32_t l = 0; - - do - { - writeDataLen += snprintf( &constructString[writeDataLen], MAX_STRING_LENGTH - writeDataLen, c->presFormat, op[l], op[l], op[l], op[l] ); - } - while ( ++l < m.len ); - } - else - { - writeDataLen = snprintf( constructString, MAX_STRING_LENGTH, c->presFormat, m.value, m.value, m.value, m.value ); - } - - written = write( opfile, constructString, ( writeDataLen < MAX_STRING_LENGTH ) ? writeDataLen : MAX_STRING_LENGTH ); - } - else - { - // raw output. - written = write( opfile, &w, sizeof ( w ) ); - } - } - while ( ( written > 0 ) && ( !c->ending ) ); - - /* Falling out on writen fail means we can re-open the fifo if it overflowed */ - close( opfile ); - } - while ( !c->ending ); - - pthread_exit( NULL ); -} -// ==================================================================================================== -static void *_runHWFifo( void *arg ) - -/* This is the control loop for the hardware fifo */ - -{ - struct runThreadParams *params = ( struct runThreadParams * )arg; - struct Channel *c = params->c; - int opfile; - size_t readDataLen = 0, writeDataLen = 0; - uint8_t p[MAX_STRING_LENGTH]; - - /* Remove the file if it exists */ - unlink( c->fifoName ); - - if ( !params->permafile ) - { - /* This is a 'conventional' fifo, so it must be created */ - if ( mkfifo( c->fifoName, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ) < 0 ) - { - pthread_exit( NULL ); - } - } - - do - { - if ( !params->permafile ) - { - /* We use RDWR to allow the open to proceed without a remote end */ - opfile = open( c->fifoName, O_RDWR | O_BINARY | O_NONBLOCK ); - } - else - { - opfile = open( c->fifoName, O_WRONLY | O_CREAT | O_BINARY | O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ); - } - - do - { - /* ....get the packet. We will hang here until a packet arrives or the link closes */ - readDataLen = read( params->listenHandle, p, MAX_STRING_LENGTH ); - - if ( readDataLen > 0 ) - { - writeDataLen = write( opfile, p, readDataLen ); - } - } - while ( ( writeDataLen > 0 ) && ( !c->ending ) ); - - /* Falling out on writeDataLen fail means we can re-open the fifo if it overflowed */ - close( opfile ); - } - while ( !c->ending ); - - pthread_exit( NULL ); -} -// ==================================================================================================== -// Decoders for each message -// ==================================================================================================== -void _handleException( struct excMsg *m, struct itmfifosHandle *f ) - -{ - char outputString[MAX_STRING_LENGTH]; - int opLen; - uint64_t eventdifftS = m->ts - f->lastHWExceptionTS; - - const char *exNames[] = {"Thread", "Reset", "NMI", "HardFault", "MemManage", "BusFault", "UsageFault", "UNKNOWN_7", - "UNKNOWN_8", "UNKNOWN_9", "UNKNOWN_10", "SVCall", "Debug Monitor", "UNKNOWN_13", "PendSV", "SysTick" - }; - const char *exEvent[] = {"Unknown", "Enter", "Exit", "Resume"}; - - f->lastHWExceptionTS = m->ts; - - if ( m->exceptionNumber < 16 ) - { - /* This is a system based exception */ - opLen = snprintf( outputString, MAX_STRING_LENGTH, "%d,%" PRIu64 ",%s,%s" EOL, HWEVENT_EXCEPTION, eventdifftS, exEvent[m->eventType & 0x03], exNames[m->exceptionNumber & 0x0F] ); - } - else - { - /* This is a CPU defined exception */ - opLen = snprintf( outputString, MAX_STRING_LENGTH, "%d,%" PRIu64 ",%s,External,%d" EOL, HWEVENT_EXCEPTION, eventdifftS, exEvent[m->eventType & 0x03], m->exceptionNumber - 16 ); - } - - write( f->c[HW_CHANNEL].handle, outputString, opLen ); -} -// ==================================================================================================== -void _handleDWTEvent( struct dwtMsg *m, struct itmfifosHandle *f ) - -{ - char outputString[MAX_STRING_LENGTH]; - int opLen; - -#define NUM_EVENTS 6 - const char *evName[NUM_EVENTS] = {"CPI", "Exc", "Sleep", "LSU", "Fold", "Cyc"}; - uint64_t eventdifftS = m->ts - f->lastHWExceptionTS; - - f->lastHWExceptionTS = m->ts; - opLen = snprintf( outputString, MAX_STRING_LENGTH, "%d,%" PRIu64, HWEVENT_DWT, eventdifftS ); - - for ( uint32_t i = 0; i < NUM_EVENTS; i++ ) - { - if ( m->event & ( 1 << i ) ) - { - // Copy this event into the output string - outputString[opLen++] = ','; - const char *u = evName[i]; - - do - { - outputString[opLen++] = *u++; - } - while ( *u ); - } - } - - write( f->c[HW_CHANNEL].handle, outputString, opLen ); - write( f->c[HW_CHANNEL].handle, EOL, strlen( EOL ) ); -} -// ==================================================================================================== -void _handlePCSample( struct pcSampleMsg *m, struct itmfifosHandle *f ) - -/* We got a sample of the PC */ - -{ - char outputString[MAX_STRING_LENGTH]; - int opLen; - uint64_t eventdifftS = m->ts - f->lastHWExceptionTS; - - f->lastHWExceptionTS = m->ts; - - if ( m->sleep ) - { - /* This is a sleep packet */ - opLen = snprintf( outputString, ( MAX_STRING_LENGTH - 1 ), "%d,%" PRIu64 ",**SLEEP**" EOL, HWEVENT_PCSample, eventdifftS ); - } - else - { - opLen = snprintf( outputString, ( MAX_STRING_LENGTH - 1 ), "%d,%" PRIu64 ",0x%08x" EOL, HWEVENT_PCSample, eventdifftS, m->pc ); - } - - /* We don't need to worry if this write does not succeed, it just means there is no other side of the fifo */ - write( f->c[HW_CHANNEL].handle, outputString, opLen ); -} -// ==================================================================================================== -void _handleDataRWWP( struct watchMsg *m, struct itmfifosHandle *f ) - -/* We got an alert due to a watch pointer */ - -{ - char outputString[MAX_STRING_LENGTH]; - int opLen; - uint64_t eventdifftS = m->ts - f->lastHWExceptionTS; - - f->lastHWExceptionTS = m->ts; - - opLen = snprintf( outputString, MAX_STRING_LENGTH, "%d,%" PRIu64 ",%d,%s,0x%x" EOL, HWEVENT_RWWT, eventdifftS, m->comp, m->isWrite ? "Write" : "Read", m->data ); - write( f->c[HW_CHANNEL].handle, outputString, opLen ); -} -// ==================================================================================================== -void _handleDataAccessWP( struct wptMsg *m, struct itmfifosHandle *f ) - -/* We got an alert due to a watchpoint */ - -{ - char outputString[MAX_STRING_LENGTH]; - int opLen; - - uint64_t eventdifftS = m->ts - f->lastHWExceptionTS; - - f->lastHWExceptionTS = m->ts; - opLen = snprintf( outputString, MAX_STRING_LENGTH, "%d,%" PRIu64 ",%d,0x%08x" EOL, HWEVENT_AWP, eventdifftS, m->comp, m->data ); - write( f->c[HW_CHANNEL].handle, outputString, opLen ); -} -// ==================================================================================================== -void _handleDataOffsetWP( struct oswMsg *m, struct itmfifosHandle *f ) - -/* We got an alert due to an offset write event */ - -{ - char outputString[MAX_STRING_LENGTH]; - int opLen; - uint64_t eventdifftS = m->ts - f->lastHWExceptionTS; - - f->lastHWExceptionTS = m->ts; - opLen = snprintf( outputString, MAX_STRING_LENGTH, "%d,%" PRIu64 ",%d,0x%04x" EOL, HWEVENT_OFS, eventdifftS, m->comp, m->offset ); - write( f->c[HW_CHANNEL].handle, outputString, opLen ); -} -// ==================================================================================================== -void _handleSW( struct swMsg *m, struct itmfifosHandle *f ) - -{ - /* Filter off filewriter packets and let the filewriter module deal with those */ - if ( ( m->srcAddr == FW_CHANNEL ) && ( f->filewriter ) ) - { - filewriterProcess( m ); - } - else - { - if ( ( m->srcAddr < NUM_CHANNELS ) && ( f->c[m->srcAddr].handle ) ) - { - write( f->c[m->srcAddr].handle, m, sizeof( struct swMsg ) ); - } - } -} -// ==================================================================================================== -void _handleNISYNC( struct nisyncMsg *m, struct itmfifosHandle *f ) - -{ - char outputString[MAX_STRING_LENGTH]; - int opLen; - - opLen = snprintf( outputString, MAX_STRING_LENGTH, "%d,%02x,0x%08x" EOL, HWEVENT_NISYNC, m->type, m->addr ); - write( f->c[HW_CHANNEL].handle, outputString, opLen ); -} - -// ==================================================================================================== -void _handleTS( struct TSMsg *m, struct itmfifosHandle *f ) - -/* ... a timestamp */ - -{ - assert( m->msgtype == MSG_TS ); - char outputString[MAX_STRING_LENGTH]; - int opLen; - - f->timeStamp += m->timeInc; - f->timeStatus = m->timeStatus; - - opLen = snprintf( outputString, MAX_STRING_LENGTH, "%d,%d,%" PRIu32 EOL, HWEVENT_TS, m->timeStatus, m->timeInc ); - write( f->c[HW_CHANNEL].handle, outputString, opLen ); -} -// ==================================================================================================== -void _itmPumpProcess( struct itmfifosHandle *f, char c ) - -/* Handle individual characters into the itm decoder */ - -{ - struct msg decoded; - - typedef void ( *handlers )( void *, struct itmfifosHandle * f ); - - /* Handlers for each complete message received */ - static const handlers h[MSG_NUM_MSGS] = - { - /* MSG_UNKNOWN */ NULL, - /* MSG_RESERVED */ NULL, - /* MSG_ERROR */ NULL, - /* MSG_NONE */ NULL, - /* MSG_SOFTWARE */ ( handlers )_handleSW, - /* MSG_NISYNC */ ( handlers )_handleNISYNC, - /* MSG_OSW */ ( handlers )_handleDataOffsetWP, - /* MSG_DATA_ACCESS_WP */ ( handlers )_handleDataAccessWP, - /* MSG_DATA_RWWP */ ( handlers )_handleDataRWWP, - /* MSG_PC_SAMPLE */ ( handlers )_handlePCSample, - /* MSG_DWT_EVENT */ ( handlers )_handleDWTEvent, - /* MSG_EXCEPTION */ ( handlers )_handleException, - /* MSG_TS */ ( handlers )_handleTS - }; - - switch ( ITMPump( &f->i, c ) ) - { - // ------------------------------------ - case ITM_EV_NONE: - break; - - // ------------------------------------ - case ITM_EV_UNSYNCED: - genericsReport( V_WARN, "ITM Lost Sync (%d)" EOL, ITMDecoderGetStats( &f->i )->lostSyncCount ); - break; - - // ------------------------------------ - case ITM_EV_SYNCED: - genericsReport( V_INFO, "ITM In Sync (%d)" EOL, ITMDecoderGetStats( &f->i )->syncCount ); - break; - - // ------------------------------------ - case ITM_EV_OVERFLOW: - genericsReport( V_WARN, "ITM Overflow (%d)" EOL, ITMDecoderGetStats( &f->i )->overflow ); - break; - - // ------------------------------------ - case ITM_EV_ERROR: - genericsReport( V_WARN, "ITM Error" EOL ); - break; - - // ------------------------------------ - case ITM_EV_PACKET_RXED: - ITMGetDecodedPacket( &f->i, &decoded ); - - /* See if we decoded a dispatchable match. genericMsg is just used to access */ - /* the first two members of the decoded structs in a portable way. */ - if ( h[decoded.genericMsg.msgtype] ) - { - ( h[decoded.genericMsg.msgtype] )( &decoded, f ); - } - - break; - - // ------------------------------------ - } -} -// ==================================================================================================== - -static void _OFLOWpacketRxed ( struct OFLOWFrame *p, void *param ) - -{ - struct itmfifosHandle *f = ( struct itmfifosHandle * )param; - - if ( !p->good ) - { - genericsReport( V_INFO, "Bad packet received" EOL ); - } - else - { - if ( p->tag == f->tag ) - { - for ( int i = 0; i < p->len; i++ ) - { - _itmPumpProcess( f, p->d[i] ); - } - } - } -} - -// ==================================================================================================== - -// ==================================================================================================== -// ==================================================================================================== -// ==================================================================================================== -// Public interface -// ==================================================================================================== -// ==================================================================================================== -// ==================================================================================================== - -// ==================================================================================================== -// Getters and Setters -// ==================================================================================================== -void itmfifoSetChanPath( struct itmfifosHandle *f, char *s ) - -{ - if ( f->chanPath ) - { - free( f->chanPath ); - } - - f->chanPath = s ? strdup( s ) : NULL; -} - -// ==================================================================================================== -// strdup leak is deliberately ignored. That is the central purpose of this code! -#pragma GCC diagnostic push -#if !defined(__clang__) - #pragma GCC diagnostic ignored "-Wanalyzer-malloc-leak" -#endif - -void itmfifoSetChannel( struct itmfifosHandle *f, int chan, char *n, char *s ) - -{ - assert( chan <= NUM_CHANNELS ); - - if ( f->c[chan].presFormat ) - { - free( f->c[chan].presFormat ); - } - - if ( f->c[chan].chanName ) - { - free( f->c[chan].chanName ); - } - - f->c[chan].chanName = strdup( n ); - - MEMCHECKV( f->c[chan].chanName ); - f->c[chan].presFormat = s ? strdup( s ) : NULL; - - MEMCHECKV( f->c[chan].presFormat ); -} -#pragma GCC diagnostic pop -// ==================================================================================================== -void itmfifoSetProtocol( struct itmfifosHandle *f, enum Prot p ) - -{ - f->protocol = p; -} -// ==================================================================================================== -void itmfifoSetForceITMSync( struct itmfifosHandle *f, bool s ) - -{ - f->forceITMSync = s; -} -// ==================================================================================================== -void itmfifoSettag( struct itmfifosHandle *f, int stream ) - -{ - f->tag = stream; -} -// ==================================================================================================== -char *itmfifoGetChannelName( struct itmfifosHandle *f, int chan ) - -{ - assert( chan <= NUM_CHANNELS ); - return f->c[chan].chanName; -} -// ==================================================================================================== -char *itmfifoGetChannelFormat( struct itmfifosHandle *f, int chan ) - -{ - assert( chan <= NUM_CHANNELS ); - return f->c[chan].chanName; -} -// ==================================================================================================== -char *itmfifoGetChanPath( struct itmfifosHandle *f ) - -{ - return f->chanPath; -} -// ==================================================================================================== -enum Prot itmfifoGetProtocol( struct itmfifosHandle *f ) - -{ - return f->protocol; -} -// ==================================================================================================== -bool itmfifoGetForceITMSync( struct itmfifosHandle *f ) - -{ - return f->forceITMSync; -} -// ==================================================================================================== -int itmfifoGettag( struct itmfifosHandle *f ) - -{ - return f->tag; -} -// ==================================================================================================== -struct ITMDecoderStats *fifoGetITMDecoderStats( struct itmfifosHandle *f ) - -{ - return ITMDecoderGetStats( &f->i ); -} -// ==================================================================================================== -// Main interface components -// ==================================================================================================== -void itmfifoProtocolPump( struct itmfifosHandle *f, uint8_t *c, int len ) - -/* Top level protocol pump */ - -{ - - if ( PROT_OFLOW == f->protocol ) - { - OFLOWPump( &f->ot, c, len, _OFLOWpacketRxed, f ); - } - else - while ( len-- ) - { - /* There's no TPIU in use, so this goes straight to the ITM layer */ - _itmPumpProcess( f, *c++ ); - } -} -// ==================================================================================================== -void itmfifoForceSync( struct itmfifosHandle *f, bool synced ) - -/* Reset and put ITM into defined state */ - -{ - ITMDecoderForceSync( &f->i, synced ); -} -// ==================================================================================================== -bool itmfifoCreate( struct itmfifosHandle *f ) - -/* Create each sub-process that will handle a port */ - -{ - int fd[2]; - - /* Make sure there's an initial timestamp to work with */ - f->lastHWExceptionTS = genericsTimestampuS(); - - /* Reset the handler before we start */ - OFLOWInit( &f->ot ); - ITMDecoderInit( &f->i, f->forceITMSync ); - - /* Cycle through channels and create a fifo for each one that is enabled */ - for ( int t = 0; t < ( NUM_CHANNELS + 1 ); t++ ) - { - if ( t < NUM_CHANNELS ) - { - if ( f->c[t].chanName ) - { - /* This is a live software channel fifo */ - if ( pipe( fd ) < 0 ) - { - return false; - } - - if ( !f->permafile ) - { - /* If this is not a permanent file then some data is allowed to get lost */ - fcntl( fd[1], F_SETFL, O_NONBLOCK ); - } - - f->c[t].handle = fd[1]; - f->c[t].ending = false; - - f->c[t].params.listenHandle = fd[0]; - f->c[t].params.portNo = t; - f->c[t].params.permafile = f->permafile; - f->c[t].params.c = &f->c[t]; - - f->c[t].fifoName = ( char * )calloc( strlen( f->c[t].chanName ) + 2 + ( f->chanPath ? strlen( f->chanPath ) : 0 ), 1 ); - - if ( f->chanPath ) - { - strcpy( f->c[t].fifoName, f->chanPath ); - strcat( f->c[t].fifoName, "/" ); - } - - strcat( f->c[t].fifoName, f->c[t].chanName ); - - if ( pthread_create( &( f->c[t].thread ), NULL, &_runFifo, &( f->c[t].params ) ) ) - { - return false; - } - } - } - else - { - /* This is the hardware fifo channel */ - if ( pipe( fd ) < 0 ) - { - return false; - } - - if ( !f->permafile ) - { - /* If this is not a permanent file then some data is allowed to get lost */ - fcntl( fd[1], F_SETFL, O_NONBLOCK ); - } - - f->c[t].handle = fd[1]; - - f->c[t].params.listenHandle = fd[0]; - f->c[t].params.portNo = t; - f->c[t].params.permafile = f->permafile; - f->c[t].params.c = &f->c[t]; - - f->c[t].fifoName = ( char * )calloc( strlen( HWFIFO_NAME ) + 2 + ( ( f->chanPath ) ? strlen( f->chanPath ) : 0 ), 1 ); - - if ( f->chanPath ) - { - strcpy( f->c[t].fifoName, f->chanPath ); - strcat( f->c[t].fifoName, "/" ); - } - - strcat( f->c[t].fifoName, HWFIFO_NAME ); - - if ( pthread_create( &( f->c[t].thread ), NULL, &_runHWFifo, &( f->c[t].params ) ) ) - { - return false; - } - } - } - - return true; -} -// ==================================================================================================== -void itmfifoShutdown( struct itmfifosHandle *f ) - -/* Destroy the per-port sub-processes. These will terminate when the fifos close */ - -{ - if ( f->amEnding ) - { - return; - } - - f->amEnding = true; - - /* Firstly go tell everything they're doomed */ - for ( int t = 0; t < NUM_CHANNELS + 1; t++ ) - { - f->c[t].ending = true; - - if ( f->c[t].handle > 0 ) - { - /* This will cause the read to end, thus terminating the pthread */ - close( f->c[t].handle ); - } - } - - /* ...now clean up */ - for ( int t = 0; t < NUM_CHANNELS + 1; t++ ) - { - if ( f->c[t].handle > 0 ) - { - pthread_join( f->c[t].thread, NULL ); - - if ( ! f->permafile ) - { - unlink( f->c[t].fifoName ); - } - } - - /* Remove the name string too */ - if ( f->c[t].presFormat ) - { - free( f->c[t].presFormat ); - } - } -} -// ==================================================================================================== - -void itmfifoFilewriter( struct itmfifosHandle *f, bool useFilewriter, char *workingPath ) - -{ - f->filewriter = useFilewriter; - - if ( f->filewriter ) - { - filewriterInit( workingPath ); - } -} - -// ==================================================================================================== -void itmfifoUsePermafiles( struct itmfifosHandle *f, bool usePermafilesSet ) - -{ - f->permafile = usePermafilesSet; -} -// ==================================================================================================== -struct itmfifosHandle *itmfifoInit( bool forceITMSyncSet, enum Prot p, int tag ) - -{ - struct itmfifosHandle *f = ( struct itmfifosHandle * )calloc( 1, sizeof( struct itmfifosHandle ) ); - - MEMCHECK( f, NULL ); - - f->chanPath = strdup( "" ); - f->protocol = p; - f->forceITMSync = forceITMSyncSet; - f->tag = tag; - return f; -} -// ==================================================================================================== diff --git a/Src/msgDecoder.c b/Src/msgDecoder.c index 8245a3f3..610b7092 100644 --- a/Src/msgDecoder.c +++ b/Src/msgDecoder.c @@ -207,17 +207,17 @@ static bool _handleTS( struct ITMPacket *packet, struct TSMsg *decoded ) if ( packet->len > 2 ) { - stamp |= ( packet->d[2] ) << 7; + stamp |= ( packet->d[2] & 0x7F ) << 7; + } - if ( packet->len > 3 ) - { - stamp |= ( packet->d[3] & 0x7F ) << 14; + if ( packet->len > 3 ) + { + stamp |= ( packet->d[3] & 0x7F ) << 14; + } - if ( packet->len > 4 ) - { - stamp |= ( packet->d[4] & 0x7f ) << 21; - } - } + if ( packet->len > 4 ) + { + stamp |= ( packet->d[4] & 0x7f ) << 21; } } diff --git a/Src/orbcat.c b/Src/orbcat.c index 66951182..81ac7fc4 100644 --- a/Src/orbcat.c +++ b/Src/orbcat.c @@ -28,9 +28,8 @@ #include "oflow.h" #define NUM_CHANNELS 32 -#define HW_CHANNEL (NUM_CHANNELS) /* Make the hardware fifo on the end of the software ones */ -#define MAX_STRING_LENGTH (4096) /* Maximum length that will be output */ +#define MAX_STRING_LENGTH (4096*4) /* Maximum length that will be output */ #define DEFAULT_TS_TRIGGER '\n' /* Default trigger character for timestamp output */ #define MSG_REORDER_BUFLEN (10) /* Maximum number of samples to re-order for timekeeping */ @@ -46,7 +45,8 @@ #define ABS_FORMAT C_TSTAMP "%s.%03" PRIu64"|" C_RESET #define STAMP_FORMAT C_TSTAMP "%12" PRIu64 "|" C_RESET #define STAMP_FORMAT_MS C_TSTAMP "%8" PRIu64 ".%03" PRIu64 "_%03" PRIu64 "|" C_RESET -#define STAMP_FORMAT_MS_DELTA C_TSTAMP "%5" PRIu64 ".%03" PRIu64 "_%03" PRIu64 "|" C_RESET +//#define STAMP_FORMAT_MS_DELTA C_TSTAMP "%5" PRIu64 ".%03" PRIu64 "_%03" PRIu64 "|" C_RESET +#define STAMP_FORMAT_MS_DELTA C_TSTAMP "%5" PRIu64 ".%03" PRIu64 "_%03" PRIu64 "_%01" PRIu64 "|" C_RESET enum TSType { TSNone, TSAbsolute, TSRelative, TSDelta, TSStamp, TSStampDelta, TSNumTypes }; @@ -217,8 +217,9 @@ static void _printTimestamp( char *strstore ) if ( options.cps ) { - uint64_t tms = ( delta * 1000000 ) / options.cps; - sprintf( strstore, STAMP_FORMAT_MS_DELTA, tms / 1000000, ( tms / 1000 ) % 1000, tms % 1000 ); + /* Provide some rounding .. we're at the limits of what's sensible here */ + uint64_t tms = ( delta * 10000000 + options.cps / 2 ) / options.cps; + sprintf( strstore, STAMP_FORMAT_MS_DELTA, tms / 10000000, ( tms / 10000 ) % 10000, ( tms / 10 ) % 1000, tms % 10 ); } else { @@ -246,7 +247,7 @@ static void _outputText( char *p ) if ( !_r.inLine ) { _printTimestamp( opConstruct ); - genericsPrintf( "%s", opConstruct ); + genericsFPrintf( stdout, "%s", opConstruct ); _r.inLine = true; } @@ -256,21 +257,21 @@ static void _outputText( char *p ) if ( q ) { *q = 0; - genericsPrintf( "%s" EOL, p ); + genericsFPrintf( stdout, "%s" EOL, p ); /* Once we've output these data then we're not in a line any more */ _r.inLine = false; /* ...and if there were any DWT messages to print we'd better output those */ if ( _r.dwtText[0] ) { - genericsPrintf( "%s" EOL, _r.dwtText ); + genericsFPrintf( stdout, "%s" EOL, _r.dwtText ); _r.dwtText[0] = 0; } } else { /* Just output the whole of the data we've got, then we're done */ - genericsPrintf( "%s", p ); + genericsFPrintf( stdout, "%s", p ); break; } @@ -296,7 +297,7 @@ void _expex( const char *fmt, ... ) /* See if we exceeded max length...if so then output what we have and start a fresh buffer */ if ( MAX_STRING_LENGTH - strlen( _r.dwtText ) < 100 ) { - genericsPrintf( "%s", _r.dwtText ); + genericsFPrintf( stdout, "%s", _r.dwtText ); _r.dwtText[0] = 0; } @@ -310,7 +311,7 @@ void _expex( const char *fmt, ... ) if ( !_r.inLine ) { - genericsPrintf( "%s", _r.dwtText ); + genericsFPrintf( stdout, "%s", _r.dwtText ); _r.dwtText[0] = 0; } } @@ -549,30 +550,30 @@ static void _itmPumpProcess( char c ) static void _printHelp( const char *const progName ) { - genericsPrintf( "Usage: %s [options]" EOL, progName ); - genericsPrintf( " -c, --channel: , of channel to add into output stream (repeat per channel)" EOL ); - genericsPrintf( " -C, --cpufreq: (Scaled) speed of the CPU" EOL - " generally /1, /4, /16 or /64 of the real CPU speed," EOL ); - genericsPrintf( " -E, --eof: Terminate when the file/socket ends/is closed, or wait for more/reconnect" EOL ); - genericsPrintf( " -f, --input-file: Take input from specified file" EOL ); - genericsPrintf( " -g, --trigger: to use to trigger timestamp (default is newline)" EOL ); - genericsPrintf( " -h, --help: This help" EOL ); - genericsPrintf( " -n, --itm-sync: Enforce sync requirement for ITM (i.e. ITM needs to issue syncs)" EOL ); - genericsPrintf( " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ITM" EOL ); - genericsPrintf( " -s, --server: : to use" EOL ); - genericsPrintf( " -t, --tag: : Which orbflow tag to use (normally 1)" EOL ); - genericsPrintf( " -T, --timestamp: : Add absolute, relative (to session start)," EOL - " delta, system timestamp or system timestamp delta to output. Note" EOL - " the accuracy of a,r & d are host dependent." EOL ); - genericsPrintf( " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); - genericsPrintf( " -V, --version: Print version and exit" EOL ); - genericsPrintf( " -x, --exceptions: Include exception information in output, in time order" EOL ); + genericsFPrintf( stderr, "Usage: %s [options]" EOL, progName ); + genericsFPrintf( stderr, " -c, --channel: , of channel to add into output stream (repeat per channel)" EOL ); + genericsFPrintf( stderr, " -C, --cpufreq: (Scaled) speed of the CPU" EOL + " generally /1, /4, /16 or /64 of the real CPU speed," EOL ); + genericsFPrintf( stderr, " -E, --eof: Terminate when the file/socket ends/is closed, or wait for more/reconnect" EOL ); + genericsFPrintf( stderr, " -f, --input-file: Take input from specified file" EOL ); + genericsFPrintf( stderr, " -g, --trigger: to use to trigger timestamp (default is newline)" EOL ); + genericsFPrintf( stderr, " -h, --help: This help" EOL ); + genericsFPrintf( stderr, " -n, --itm-sync: Enforce sync requirement for ITM (i.e. ITM needs to issue syncs)" EOL ); + genericsFPrintf( stderr, " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ITM" EOL ); + genericsFPrintf( stderr, " -s, --server: : to use" EOL ); + genericsFPrintf( stderr, " -t, --tag: : Which orbflow tag to use (normally 1)" EOL ); + genericsFPrintf( stderr, " -T, --timestamp: : Add absolute, relative (to session start)," EOL + " delta, system timestamp or system timestamp delta to output. Note" EOL + " the accuracy of a,r & d are host dependent." EOL ); + genericsFPrintf( stderr, " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); + genericsFPrintf( stderr, " -V, --version: Print version and exit" EOL ); + genericsFPrintf( stderr, " -x, --exceptions: Include exception information in output, in time order" EOL ); } // ==================================================================================================== static void _printVersion( void ) { - genericsPrintf( "orbcat version " GIT_DESCRIBE EOL ); + genericsFPrintf( stderr, "orbcat version " GIT_DESCRIBE EOL ); } // ==================================================================================================== static struct option _longOptions[] = @@ -989,7 +990,7 @@ static void _feedStream( struct Stream *stream ) /* Check if an exception report timed out */ if ( ( _r.inLine ) && _r.dwtText[0] && ( _timestamp() - _r.dwtte > DWT_TO_US ) ) { - genericsPrintf( EOL "%s", _r.dwtText ); + genericsFPrintf( stderr, EOL "%s", _r.dwtText ); _r.dwtText[0] = 0; _r.inLine = false; } diff --git a/Src/orbdump.c b/Src/orbdump.c index a5116cc1..a6c59991 100644 --- a/Src/orbdump.c +++ b/Src/orbdump.c @@ -22,7 +22,7 @@ #include "nw.h" -#define MAX_STRING_LENGTH (256) /* Maximum length that will be output from a fifo for a single event */ +#define MAX_STRING_LENGTH (256) /* Maximum length that will be output for a single event */ #define DEFAULT_OUTFILE "/dev/stdout" #define DEFAULT_TIMELEN 10000 @@ -98,24 +98,24 @@ uint64_t _timestamp( void ) void _printHelp( const char *const progName ) { - genericsPrintf( "Usage: %s [options]" EOL, progName ); - genericsPrintf( " -h, --help: This help" EOL ); - genericsPrintf( " -l, --length: Length of time in ms to record from point of acheiving sync (defaults to %dmS)" EOL, options.timelen ); - genericsPrintf( " -M, --no-colour: Supress colour in output" EOL ); - genericsPrintf( " -n, --itm-sync: Enforce sync requirement for ITM (i.e. ITM needs to issue syncs)" EOL ); - genericsPrintf( " -o, --output-file: to be used for dump file (defaults to %s)" EOL, options.outfile ); - genericsPrintf( " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ITM" EOL ); - genericsPrintf( " -s, --server: : to use" EOL ); - genericsPrintf( " -t, --tag: Which Orbflow tag to use (normally 1)" EOL ); - genericsPrintf( " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); - genericsPrintf( " -V, --version: Print version and exit" EOL ); - genericsPrintf( " -w, --sync-write: Write synchronously to the output file after every packet" EOL ); + genericsFPrintf( stderr, "Usage: %s [options]" EOL, progName ); + genericsFPrintf( stderr, " -h, --help: This help" EOL ); + genericsFPrintf( stderr, " -l, --length: Length of time in ms to record from point of acheiving sync (defaults to %dmS)" EOL, options.timelen ); + genericsFPrintf( stderr, " -M, --no-colour: Supress colour in output" EOL ); + genericsFPrintf( stderr, " -n, --itm-sync: Enforce sync requirement for ITM (i.e. ITM needs to issue syncs)" EOL ); + genericsFPrintf( stderr, " -o, --output-file: to be used for dump file (defaults to %s)" EOL, options.outfile ); + genericsFPrintf( stderr, " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ITM" EOL ); + genericsFPrintf( stderr, " -s, --server: : to use" EOL ); + genericsFPrintf( stderr, " -t, --tag: Which Orbflow tag to use (normally 1)" EOL ); + genericsFPrintf( stderr, " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); + genericsFPrintf( stderr, " -V, --version: Print version and exit" EOL ); + genericsFPrintf( stderr, " -w, --sync-write: Write synchronously to the output file after every packet" EOL ); } // ==================================================================================================== void _printVersion( void ) { - genericsPrintf( "orbdump version " GIT_DESCRIBE EOL ); + genericsFPrintf( stderr, "orbdump version " GIT_DESCRIBE EOL ); } // ==================================================================================================== static struct option _longOptions[] = diff --git a/Src/orbfifo.c b/Src/orbfifo.c deleted file mode 100644 index 78803583..00000000 --- a/Src/orbfifo.c +++ /dev/null @@ -1,549 +0,0 @@ -/* SPDX-License-Identifier: BSD-3-Clause */ - -/* - * ITM Splitter for Orbuculum - * ========================== - * - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "git_version_info.h" -#include "generics.h" -#include "fileWriter.h" -#include "stream.h" -#include "nw.h" - -#include "itmfifos.h" - -const char *protString[] = {"OFLOW", "ITM", NULL}; - -//#define DUMP_BLOCK - -/* Record for options, either defaults or from command line */ -struct -{ - /* Config information */ - bool filewriter; /* Supporting filewriter functionality */ - char *fwbasedir; /* Base directory for filewriter output */ - bool permafile; /* Use permanent files rather than fifos */ - - /* Source information */ - char *file; /* File host connection */ - bool fileTerminate; /* Terminate when file read isn't successful */ - bool mono; /* Supress colour in output */ - - int port; /* Source information */ - char *server; - -} options = -{ - .port = OFCLIENT_SERVER_PORT, - .server = "localhost" -}; - -struct -{ - struct itmfifosHandle *f; /* Link to the itmfifo subsystem */ - bool ending; /* Flag indicating app is terminating */ -} _r; - -// ==================================================================================================== -// ==================================================================================================== -// ==================================================================================================== -// Private routines -// ==================================================================================================== -// ==================================================================================================== -// ==================================================================================================== -static void _printHelp( const char *const progName ) - -{ - genericsPrintf( "Usage: %s [options]" EOL, progName ); - genericsPrintf( " -b, --basedir: for channels" EOL ); - genericsPrintf( " -c, --channel: ,, of channel to populate (repeat per channel)" EOL ); - genericsPrintf( " -E, --eof: When reading from file, terminate at end of file" EOL ); - genericsPrintf( " -f, --input-file: Take input from specified file" EOL ); - genericsPrintf( " -h, --help: This help" EOL ); - genericsPrintf( " -M, --no-colour: Supress colour in output" EOL ); - genericsPrintf( " -P, --permanent: Create permanent files rather than fifos" EOL ); - genericsPrintf( " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ITM" EOL ); - genericsPrintf( " -s, --server: : to use" EOL ); - genericsPrintf( " -t, --tag: Which OFLOW tag to use (normally 1)" EOL ); - genericsPrintf( " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); - genericsPrintf( " -V, --version: Print version and exit" EOL ); - genericsPrintf( " -W, --writer-path: Enable filewriter functionality using specified base path" EOL ); -} -// ==================================================================================================== -void _printVersion( void ) - -{ - genericsPrintf( "orbfifo version " GIT_DESCRIBE ); -} -// ==================================================================================================== -struct option _longOptions[] = -{ - {"basedir", required_argument, NULL, 'b'}, - {"channel", required_argument, NULL, 'c'}, - {"eof", no_argument, NULL, 'E'}, - {"input-file", required_argument, NULL, 'f'}, - {"help", no_argument, NULL, 'h'}, - {"no-colour", no_argument, NULL, 'M'}, - {"no-color", no_argument, NULL, 'M'}, - {"permanent", no_argument, NULL, 'P'}, - {"protocol", required_argument, NULL, 'p'}, - {"server", required_argument, NULL, 's'}, - {"tag", required_argument, NULL, 't'}, - {"verbose", required_argument, NULL, 'v'}, - {"version", no_argument, NULL, 'V'}, - {"writer-path", required_argument, NULL, 'W'}, - {NULL, no_argument, NULL, 0} -}; -// ==================================================================================================== -static bool _processOptions( int argc, char *argv[] ) - -{ - int c, optionIndex = 0; -#define DELIMITER ',' - - char *chanConfig; - char *chanName; - uint chan; - char *chanIndex; - bool protExplicit = false; - bool serverExplicit = false; - bool portExplicit = false; - enum Prot p; - - while ( ( c = getopt_long ( argc, argv, "b:c:Ef:hVn:Pp:s:t:v:w:", _longOptions, &optionIndex ) ) != -1 ) - switch ( c ) - { - // ------------------------------------ - - case 'b': - itmfifoSetChanPath( _r.f, optarg ); - break; - - // ------------------------------------ - case 'E': - options.fileTerminate = true; - break; - - // ------------------------------------ - - case 'f': - options.file = optarg; - break; - - // ------------------------------------ - - case 'h': - _printHelp( argv[0] ); - return false; - - // ------------------------------------ - case 'V': - _printVersion(); - return false; - - // ------------------------------------ - case 'M': - options.mono = true; - break; - - // ------------------------------------ - case 'n': - itmfifoSetForceITMSync( _r.f, false ); - break; - - // ------------------------------------ - - case 'P': - options.permafile = true; - break; - - // ------------------------------------ - - case 'p': - p = PROT_UNKNOWN; - protExplicit = true; - - for ( int i = 0; protString[i]; i++ ) - { - if ( !strcmp( protString[i], optarg ) ) - { - p = i; - break; - } - } - - if ( PROT_UNKNOWN == p ) - { - genericsReport( V_ERROR, "Unrecognised protocol type" EOL ); - return false; - } - - itmfifoSetProtocol( _r.f, p ); - break; - - // ------------------------------------ - case 's': - options.server = optarg; - serverExplicit = true; - - // See if we have an optional port number too - char *a = optarg; - - while ( ( *a ) && ( *a != ':' ) ) - { - a++; - } - - if ( *a == ':' ) - { - *a = 0; - options.port = atoi( ++a ); - } - - if ( !options.port ) - { - options.port = NWCLIENT_SERVER_PORT; - } - else - { - portExplicit = true; - } - - break; - - // ------------------------------------ - - case 't': - itmfifoSettag( _r.f, atoi( optarg ) ); - break; - - // ------------------------------------ - - case 'v': - if ( !isdigit( *optarg ) ) - { - genericsReport( V_ERROR, "-v requires a numeric argument." EOL ); - return false; - } - - genericsSetReportLevel( atoi( optarg ) ); - break; - - // ------------------------------------ - - case 'W': - options.filewriter = true; - options.fwbasedir = optarg; - break; - - // ------------------------------------ - - /* Individual channel setup */ - case 'c': - chanIndex = chanConfig = strdup( optarg ); - - if ( NULL == chanConfig ) - { - genericsReport( V_ERROR, "Couldn't allocate memory at %s::%d" EOL, __FILE__, __LINE__ ); - return false; - } - - chan = atoi( optarg ); - - if ( chan >= NUM_CHANNELS ) - { - genericsReport( V_ERROR, "Channel index out of range" EOL ); - free( chanConfig ); - return false; - } - - /* Scan for start of filename */ - while ( ( *chanIndex ) && ( *chanIndex != DELIMITER ) ) - { - chanIndex++; - } - - if ( !*chanIndex ) - { - genericsReport( V_ERROR, "No filename for channel %d" EOL, chan ); - free( chanConfig ); - return false; - } - - chanName = ++chanIndex; - - /* Scan for format */ - while ( ( *chanIndex ) && ( *chanIndex != DELIMITER ) ) - { - chanIndex++; - } - - if ( !*chanIndex ) - { - genericsReport( V_WARN, "No output format for channel %d, output raw!" EOL, chan ); - itmfifoSetChannel( _r.f, chan, chanName, NULL ); - break; - } - - *chanIndex++ = 0; - itmfifoSetChannel( _r.f, chan, chanName, genericsUnescape( chanIndex ) ); - break; - - // ------------------------------------ - - case '?': - if ( optopt == 'b' ) - { - genericsReport( V_ERROR, "Option '%c' requires an argument." EOL, optopt ); - } - else if ( !isprint ( optopt ) ) - { - genericsReport( V_ERROR, "Unknown option character `\\x%x'." EOL, optopt ); - } - - return false; - - // ------------------------------------ - default: - genericsReport( V_ERROR, "Unrecognised option '%c'" EOL, c ); - return false; - // ------------------------------------ - } - - /* If we set an explicit server and port and didn't set a protocol chances are we want ITM, not OFLOW */ - if ( serverExplicit && !protExplicit ) - { - itmfifoSetProtocol( _r.f, PROT_ITM ); - } - - if ( ( itmfifoGetProtocol( _r.f ) == PROT_ITM ) && !portExplicit ) - { - options.port = NWCLIENT_SERVER_PORT; - } - - - /* ... and dump the config if we're being verbose */ - genericsReport( V_INFO, "orbfifo version " GIT_DESCRIBE EOL ); - genericsReport( V_INFO, "Server : %s:%d" EOL, options.server, options.port ); - - if ( options.file ) - { - genericsReport( V_INFO, "Input File : %s", options.file ); - - if ( options.fileTerminate ) - { - genericsReport( V_INFO, " (Terminate on exhaustion)" EOL ); - } - else - { - genericsReport( V_INFO, " (Ongoing read)" EOL ); - } - } - - - switch ( itmfifoGetProtocol( _r.f ) ) - { - case PROT_OFLOW: - genericsReport( V_INFO, "Decoding OFLOW (Orbuculum) with ITM in stream %d" EOL, itmfifoGettag( _r.f ) ); - break; - - case PROT_ITM: - genericsReport( V_INFO, "Decoding ITM" EOL ); - break; - - default: - genericsReport( V_INFO, "Decoding unknown" EOL ); - break; - } - - genericsReport( V_INFO, "Channels :" EOL ); - - for ( int g = 0; g < NUM_CHANNELS; g++ ) - { - if ( itmfifoGetChannelName( _r.f, g ) ) - { - genericsReport( V_INFO, " %02d [%s] [%s]" EOL, g, genericsEscape( itmfifoGetChannelFormat( _r.f, g ) ? : "RAW" ), itmfifoGetChannelName( _r.f, g ) ); - } - } - - genericsReport( V_INFO, " HW [Predefined] [" HWFIFO_NAME "]" EOL ); - - return true; -} -// ==================================================================================================== -static void _processBlock( int s, unsigned char *cbw ) - -/* Generic block processor for received data */ - -{ - genericsReport( V_DEBUG, "RXED Packet of %d bytes" EOL, s ); - - if ( s ) - { -#ifdef DUMP_BLOCK - uint8_t *c = cbw; - uint32_t y = s; - - fprintf( stderr, EOL ); - - while ( y-- ) - { - fprintf( stderr, "%02X ", *c++ ); - - if ( !( y % 16 ) ) - { - fprintf( stderr, EOL ); - } - } - -#endif - - itmfifoProtocolPump( _r.f, cbw, s ); - } - -} -// ==================================================================================================== -static void _doExit( void ) - -{ - _r.ending = true; - itmfifoShutdown( _r.f ); - /* Give them a bit of time, then we're leaving anyway */ - usleep( 200 ); -} - -// ==================================================================================================== -static void _intHandler( int sig ) - -{ - /* CTRL-C exit is not an error... */ - _doExit(); -} - -// ==================================================================================================== -int main( int argc, char *argv[] ) - -{ - uint8_t cbw[TRANSFER_SIZE]; - size_t t; - struct Stream *stream = NULL; - int64_t lastTime; - struct timeval tv; - uint64_t remainTime; - - /* Setup fifos with forced ITM sync, tag 1 */ - _r.f = itmfifoInit( true, false, 1 ); - assert( _r.f ); - - if ( !_processOptions( argc, argv ) ) - { - /* processOptions generates its own error messages */ - genericsExit( -1, "" EOL ); - } - - genericsScreenHandling( !options.mono ); - - itmfifoUsePermafiles( _r.f, options.permafile ); - - /* Make sure the fifos get removed at the end */ - atexit( _doExit ); - - /* Fill in a time to start from */ - lastTime = genericsTimestampmS(); - - /* This ensures the atexit gets called */ - if ( SIG_ERR == signal( SIGINT, _intHandler ) ) - { - genericsExit( -1, "Failed to establish Int handler" EOL ); - } - - /* Don't kill a sub-process when any reader or writer evaporates */ - if ( SIG_ERR == signal( SIGPIPE, SIG_IGN ) ) - { - genericsExit( -1, "Failed to ignore SIGPIPEs" EOL ); - } - - if ( ! ( itmfifoCreate( _r.f ) ) ) - { - genericsExit( -1, "Failed to make channel devices" EOL ); - } - - /* Start the filewriter */ - itmfifoFilewriter( _r.f, options.filewriter, options.fwbasedir ); - - while ( !_r.ending ) - { - if ( options.file != NULL ) - { - stream = streamCreateFile( options.file ); - } - else - { - while ( !_r.ending ) - { - stream = streamCreateSocket( options.server, options.port ); - - if ( stream ) - { - break; - } - - genericsReport( V_INFO, "Could not connect" EOL ); - usleep( 1000000 ); - } - } - - while ( !_r.ending ) - { - remainTime = ( ( lastTime + 1000000 - genericsTimestampuS() ) ); - - if ( remainTime > 0 ) - { - tv.tv_sec = remainTime / 1000000; - tv.tv_usec = remainTime % 1000000; - } - - enum ReceiveResult result = stream->receive( stream, cbw, TRANSFER_SIZE, &tv, ( size_t * )&t ); - - if ( ( result == RECEIVE_RESULT_EOF ) || ( result == RECEIVE_RESULT_ERROR ) ) - { - break; - } - - _processBlock( t, cbw ); - } - - - if ( stream ) - { - stream->close( stream ); - free( stream ); - stream = NULL; - } - - if ( options.fileTerminate ) - { - break; - } - } - - return -ESRCH; -} -// ==================================================================================================== diff --git a/Src/orblcd.c b/Src/orblcd.c index 0bb6856e..51495d3b 100644 --- a/Src/orblcd.c +++ b/Src/orblcd.c @@ -122,12 +122,20 @@ static void _paintPixels( struct swMsg *m, struct RunTime *r ) return; } - for ( int b = ORBLCD_PIXELS_PER_WORD( r->app->modeDescriptor ) - 1; b >= 0; b-- ) + for ( int b = m->len*8/ORBLCD_GET_DEPTH( r->app->modeDescriptor ) - 1; b >= 0; b-- ) + //for ( int b = ORBLCD_PIXELS_PER_WORD( r->app->modeDescriptor ) - 1; b >= 0; b-- ) { switch ( ORBLCD_DECODE_D( r->app->modeDescriptor ) ) { case ORBLCD_DEPTH_1: - y = ( d & ( 1 << ( b % 8 ) ) ) ? r->app->sbcolour : 0; + if ( ORBLCD_DECODE_L( r->app->modeDescriptor ) ) + { + y = ( d & ( 128 >> ( b % 8 ) ) ) ? r->app->sbcolour : 0; + } + else + { + y = ( d & ( 1 << ( b % 8 ) ) ) ? r->app->sbcolour : 0; + } if ( !( b % 8 ) ) { @@ -422,26 +430,26 @@ static bool _feedStream( struct Stream *stream, struct RunTime *r ) void _printHelp( const char *const progName ) { - genericsPrintf( "Usage: %s [options]" EOL, progName ); - genericsPrintf( " -c, --channel: of first channel in pair containing display data" EOL ); - genericsPrintf( " -f, --input-file: Take input from specified file" EOL ); - genericsPrintf( " -h, --help: This help" EOL ); - genericsPrintf( " -n, --itm-sync: Enforce sync requirement for ITM (i.e. ITM needs to issue syncs)" EOL ); - genericsPrintf( " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ITM" EOL ); - genericsPrintf( " -s, --server: : to use" EOL ); - genericsPrintf( " -S, --sbcolour: to be used for single bit renders, ignored for other bit depths" EOL ); - genericsPrintf( " -t, --tag: Which OFLOW tag to use (normally 1)" EOL ); - genericsPrintf( " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); - genericsPrintf( " -V, --version: Print version and exit" EOL ); - genericsPrintf( " -w, --window: Set title for output window" EOL ); - genericsPrintf( " -z, --size: Set relative size of output window (normally 1.0)" EOL ); + genericsFPrintf( stderr, "Usage: %s [options]" EOL, progName ); + genericsFPrintf( stderr, " -c, --channel: of first channel in pair containing display data" EOL ); + genericsFPrintf( stderr, " -f, --input-file: Take input from specified file" EOL ); + genericsFPrintf( stderr, " -h, --help: This help" EOL ); + genericsFPrintf( stderr, " -n, --itm-sync: Enforce sync requirement for ITM (i.e. ITM needs to issue syncs)" EOL ); + genericsFPrintf( stderr, " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ITM" EOL ); + genericsFPrintf( stderr, " -s, --server: : to use" EOL ); + genericsFPrintf( stderr, " -S, --sbcolour: to be used for single bit renders, ignored for other bit depths" EOL ); + genericsFPrintf( stderr, " -t, --tag: Which OFLOW tag to use (normally 1)" EOL ); + genericsFPrintf( stderr, " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); + genericsFPrintf( stderr, " -V, --version: Print version and exit" EOL ); + genericsFPrintf( stderr, " -w, --window: Set title for output window" EOL ); + genericsFPrintf( stderr, " -z, --size: Set relative size of output window (normally 1.0)" EOL ); } // ==================================================================================================== void _printVersion( void ) { - genericsPrintf( "orblcd version " GIT_DESCRIBE EOL ); + genericsFPrintf( stderr, "orblcd version " GIT_DESCRIBE EOL ); } // ==================================================================================================== static struct option _longOptions[] = diff --git a/Src/orbmortem.c b/Src/orbmortem.c index 1d7442f4..495e2c76 100644 --- a/Src/orbmortem.c +++ b/Src/orbmortem.c @@ -167,41 +167,41 @@ static void _intHandler( int sig ) static void _printHelp( const char *const progName ) { - genericsPrintf( "Usage: %s [options]" EOL, progName ); - genericsPrintf( " -A, --alt-addr-enc: Do not use alternate address encoding" EOL ); - genericsPrintf( " -b, --buffer-len: Length of post-mortem buffer, in KBytes (Default %d KBytes)" EOL, DEFAULT_PM_BUFLEN_K ); - genericsPrintf( " -C, --editor-cmd: Command line for external editor (%%f = filename, %%l = line)" EOL ); - genericsPrintf( " -D, --no-demangle: Switch off C++ symbol demangling" EOL ); - genericsPrintf( " -d, --del-prefix: Material to delete off the front of filenames" EOL ); - genericsPrintf( " -e, --elf-file: to use for symbols and source" EOL ); - genericsPrintf( " -E, --eof: When reading from file, terminate at end of file" EOL ); - genericsPrintf( " -f, --input-file: : Take input from specified file" EOL ); - genericsPrintf( " -h, --help: This help" EOL ); - genericsPrintf( " -M, --no-colour: Supress colour in output" EOL ); - genericsPrintf( " -O, --objdump-opts: Options to pass directly to objdump" EOL ); - genericsPrintf( " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ETM" EOL ); - genericsPrintf( " -P, --trace-proto: { " ); + genericsFPrintf( stderr, "Usage: %s [options]" EOL, progName ); + genericsFPrintf( stderr, " -A, --alt-addr-enc: Do not use alternate address encoding" EOL ); + genericsFPrintf( stderr, " -b, --buffer-len: Length of post-mortem buffer, in KBytes (Default %d KBytes)" EOL, DEFAULT_PM_BUFLEN_K ); + genericsFPrintf( stderr, " -C, --editor-cmd: Command line for external editor (%%f = filename, %%l = line)" EOL ); + genericsFPrintf( stderr, " -D, --no-demangle: Switch off C++ symbol demangling" EOL ); + genericsFPrintf( stderr, " -d, --del-prefix: Material to delete off the front of filenames" EOL ); + genericsFPrintf( stderr, " -e, --elf-file: to use for symbols and source" EOL ); + genericsFPrintf( stderr, " -E, --eof: When reading from file, terminate at end of file" EOL ); + genericsFPrintf( stderr, " -f, --input-file: : Take input from specified file" EOL ); + genericsFPrintf( stderr, " -h, --help: This help" EOL ); + genericsFPrintf( stderr, " -M, --no-colour: Supress colour in output" EOL ); + genericsFPrintf( stderr, " -O, --objdump-opts: Options to pass directly to objdump" EOL ); + genericsFPrintf( stderr, " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ETM" EOL ); + genericsFPrintf( stderr, " -P, --trace-proto: { " ); for ( int i = TRACE_PROT_LIST_START; i < TRACE_PROT_NUM; i++ ) { - genericsPrintf( "%s ", TRACEDecodeGetProtocolName( i ) ); + genericsFPrintf( stderr, "%s ", TRACEDecodeGetProtocolName( i ) ); } - genericsPrintf( "} trace protocol to use, default is %s" EOL, TRACEDecodeGetProtocolName( TRACE_PROT_LIST_START ) ); - genericsPrintf( " -s, --server: : to use" EOL ); - genericsPrintf( " -t, --tag: : Which OFLOW tag to use (normally 2)" EOL ); - genericsPrintf( " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); - genericsPrintf( " -V, --version: Print version and exit" EOL ); - genericsPrintf( EOL "(Legacy protocol will connect one port higher than that set in -s)" EOL ); - genericsPrintf( "(This will automatically select the second output stream from orbuculum.)" EOL ); - genericsPrintf( EOL "Environment Variables;" EOL ); - genericsPrintf( " OBJDUMP: to use non-standard objdump binary" EOL ); + genericsFPrintf( stderr, "} trace protocol to use, default is %s" EOL, TRACEDecodeGetProtocolName( TRACE_PROT_LIST_START ) ); + genericsFPrintf( stderr, " -s, --server: : to use" EOL ); + genericsFPrintf( stderr, " -t, --tag: : Which OFLOW tag to use (normally 2)" EOL ); + genericsFPrintf( stderr, " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); + genericsFPrintf( stderr, " -V, --version: Print version and exit" EOL ); + genericsFPrintf( stderr, EOL "(Legacy protocol will connect one port higher than that set in -s)" EOL ); + genericsFPrintf( stderr, "(This will automatically select the second output stream from orbuculum.)" EOL ); + genericsFPrintf( stderr, EOL "Environment Variables;" EOL ); + genericsFPrintf( stderr, " OBJDUMP: to use non-standard objdump binary" EOL ); } // ==================================================================================================== void _printVersion( void ) { - genericsPrintf( "orbmortem version " GIT_DESCRIBE ); + genericsFPrintf( stderr, "orbmortem version " GIT_DESCRIBE ); } // ==================================================================================================== static struct option _longOptions[] = @@ -1329,7 +1329,7 @@ int main( int argc, char *argv[] ) genericsScreenHandling( !_r.options->mono ); - /* Make sure the fifos get removed at the end */ + /* Make sure any cleanup happens at the end */ atexit( _doExit ); if ( _r.options->file != NULL ) diff --git a/Src/orbprofile.c b/Src/orbprofile.c index 6bbfe68c..2841c177 100644 --- a/Src/orbprofile.c +++ b/Src/orbprofile.c @@ -457,33 +457,33 @@ static void _traceCB( void *d ) static void _printHelp( const char *const progName ) { - genericsPrintf( "Usage: %s [options]" EOL, progName ); - genericsPrintf( " -A, --alt-addr-enc: Switch off alternate address decoding (on by default)" EOL ); - genericsPrintf( " -D, --no-demangle: Switch off C++ symbol demangling" EOL ); - genericsPrintf( " -d, --del-prefix: Material to delete off front of filenames" EOL ); - genericsPrintf( " -e, --elf-file: to use for symbols" EOL ); - genericsPrintf( " -E, --eof: When reading from file, terminate at EOF" EOL ); - genericsPrintf( " -f, --input-file: Take input from specified file" EOL ); - genericsPrintf( " -h, --help: This help" EOL ); - genericsPrintf( " -I, --interval: Time between samples (in ms)" EOL ); - genericsPrintf( " -M, --no-colour: Supress colour in output" EOL ); - genericsPrintf( " -O, --objdump-opts: Options to pass directly to objdump" EOL ); - genericsPrintf( " -P, --trace-proto: {ETM35|MTB} trace protocol to use, default is ETM35" EOL ); - genericsPrintf( " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise raw ETM" EOL ); - genericsPrintf( " -s, --server: : to use" EOL ); - genericsPrintf( " -t, --tag: : Which OFLOW tag to use (normally 2)" EOL ); - genericsPrintf( " -T, --all-truncate: truncate -d material off all references (i.e. make output relative)" EOL ); - genericsPrintf( " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); - genericsPrintf( " -V, --version: Print version and exit" EOL ); - genericsPrintf( " -y, --graph-file: dotty filename for structured callgraph output" EOL ); - genericsPrintf( " -z, --cache-file: profile filename for kcachegrind output" EOL ); - genericsPrintf( EOL "(Will connect one port higher than that set in -s when Orbflow is not used)" EOL ); + genericsFPrintf( stderr, "Usage: %s [options]" EOL, progName ); + genericsFPrintf( stderr, " -A, --alt-addr-enc: Switch off alternate address decoding (on by default)" EOL ); + genericsFPrintf( stderr, " -D, --no-demangle: Switch off C++ symbol demangling" EOL ); + genericsFPrintf( stderr, " -d, --del-prefix: Material to delete off front of filenames" EOL ); + genericsFPrintf( stderr, " -e, --elf-file: to use for symbols" EOL ); + genericsFPrintf( stderr, " -E, --eof: When reading from file, terminate at EOF" EOL ); + genericsFPrintf( stderr, " -f, --input-file: Take input from specified file" EOL ); + genericsFPrintf( stderr, " -h, --help: This help" EOL ); + genericsFPrintf( stderr, " -I, --interval: Time between samples (in ms)" EOL ); + genericsFPrintf( stderr, " -M, --no-colour: Supress colour in output" EOL ); + genericsFPrintf( stderr, " -O, --objdump-opts: Options to pass directly to objdump" EOL ); + genericsFPrintf( stderr, " -P, --trace-proto: {ETM35|MTB} trace protocol to use, default is ETM35" EOL ); + genericsFPrintf( stderr, " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise raw ETM" EOL ); + genericsFPrintf( stderr, " -s, --server: : to use" EOL ); + genericsFPrintf( stderr, " -t, --tag: : Which OFLOW tag to use (normally 2)" EOL ); + genericsFPrintf( stderr, " -T, --all-truncate: truncate -d material off all references (i.e. make output relative)" EOL ); + genericsFPrintf( stderr, " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); + genericsFPrintf( stderr, " -V, --version: Print version and exit" EOL ); + genericsFPrintf( stderr, " -y, --graph-file: dotty filename for structured callgraph output" EOL ); + genericsFPrintf( stderr, " -z, --cache-file: profile filename for kcachegrind output" EOL ); + genericsFPrintf( stderr, EOL "(Will connect one port higher than that set in -s when Orbflow is not used)" EOL ); } // ==================================================================================================== void _printVersion( void ) { - genericsPrintf( "orbprofile version " GIT_DESCRIBE ); + genericsFPrintf( stderr, "orbprofile version " GIT_DESCRIBE ); } // ==================================================================================================== static struct option _longOptions[] = @@ -866,7 +866,7 @@ int main( int argc, char *argv[] ) genericsScreenHandling( !_r.options->mono ); - /* Make sure the fifos get removed at the end */ + /* Make sure any cleanup happens at the end */ atexit( _doExit ); /* This ensures the atexit gets called */ diff --git a/Src/orbstat.c b/Src/orbstat.c index 214129eb..9014a526 100644 --- a/Src/orbstat.c +++ b/Src/orbstat.c @@ -404,32 +404,32 @@ void _itmPumpProcess( struct RunTime *r, char c ) static void _printHelp( struct RunTime *r ) { - genericsPrintf( "Usage: %s [options]" EOL, r->progName ); - genericsPrintf( " -D, --no-demangle: Switch off C++ symbol demangling" EOL ); - genericsPrintf( " -d, --del-prefix: Material to delete off front of filenames" EOL ); - genericsPrintf( " -e, --elf-file: to use for symbols" EOL ); - genericsPrintf( " -E, --eof: When reading from file, terminate at end of file" EOL ); - genericsPrintf( " -f, --input-file: : Take input from specified file" EOL ); - genericsPrintf( " -g, --trace-chn: ITM channel for trace (default %d)" EOL, r->options->traceChannel ); - genericsPrintf( " -h, --help: This help" EOL ); - genericsPrintf( " -I, --interval: : Time to sample (in mS)" EOL ); - genericsPrintf( " -n, --itm-sync: Enforce sync requirement for ITM (i.e. ITM needs to issue syncs)" EOL ); - genericsPrintf( " -M, --no-colour: Supress colour in output" EOL ); - genericsPrintf( " -O, --objdump-opts: Options to pass directly to objdump" EOL ); - genericsPrintf( " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ITM" EOL ); - genericsPrintf( " -s, --server: : to use" EOL ); - genericsPrintf( " -t, --tag: : Which OFLOW tag to use (normally 1)" EOL ); - genericsPrintf( " -T, --all-truncate: truncate -d material off all references (i.e. make output relative)" EOL ); - genericsPrintf( " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); - genericsPrintf( " -V, --version: Print version and exit" EOL ); - genericsPrintf( " -y, --graph-file: dotty filename for structured callgraph output" EOL ); - genericsPrintf( " -z, --cache-file: profile filename for kcachegrind output" EOL ); + genericsFPrintf( stderr, "Usage: %s [options]" EOL, r->progName ); + genericsFPrintf( stderr, " -D, --no-demangle: Switch off C++ symbol demangling" EOL ); + genericsFPrintf( stderr, " -d, --del-prefix: Material to delete off front of filenames" EOL ); + genericsFPrintf( stderr, " -e, --elf-file: to use for symbols" EOL ); + genericsFPrintf( stderr, " -E, --eof: When reading from file, terminate at end of file" EOL ); + genericsFPrintf( stderr, " -f, --input-file: : Take input from specified file" EOL ); + genericsFPrintf( stderr, " -g, --trace-chn: ITM channel for trace (default %d)" EOL, r->options->traceChannel ); + genericsFPrintf( stderr, " -h, --help: This help" EOL ); + genericsFPrintf( stderr, " -I, --interval: : Time to sample (in mS)" EOL ); + genericsFPrintf( stderr, " -n, --itm-sync: Enforce sync requirement for ITM (i.e. ITM needs to issue syncs)" EOL ); + genericsFPrintf( stderr, " -M, --no-colour: Supress colour in output" EOL ); + genericsFPrintf( stderr, " -O, --objdump-opts: Options to pass directly to objdump" EOL ); + genericsFPrintf( stderr, " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ITM" EOL ); + genericsFPrintf( stderr, " -s, --server: : to use" EOL ); + genericsFPrintf( stderr, " -t, --tag: : Which OFLOW tag to use (normally 1)" EOL ); + genericsFPrintf( stderr, " -T, --all-truncate: truncate -d material off all references (i.e. make output relative)" EOL ); + genericsFPrintf( stderr, " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); + genericsFPrintf( stderr, " -V, --version: Print version and exit" EOL ); + genericsFPrintf( stderr, " -y, --graph-file: dotty filename for structured callgraph output" EOL ); + genericsFPrintf( stderr, " -z, --cache-file: profile filename for kcachegrind output" EOL ); } // ==================================================================================================== void _printVersion( void ) { - genericsPrintf( "orbstat version " GIT_DESCRIBE ); + genericsFPrintf( stderr, "orbstat version " GIT_DESCRIBE ); } // ==================================================================================================== static struct option _longOptions[] = diff --git a/Src/orbtop.c b/Src/orbtop.c index df883ec2..d7d79f80 100644 --- a/Src/orbtop.c +++ b/Src/orbtop.c @@ -637,7 +637,7 @@ static void _outputTop( uint32_t total, uint32_t reportLines, struct reportLine q = fopen( options.logfile, "a" ); } - genericsPrintf( CLEAR_SCREEN ); + genericsFPrintf( stdout, CLEAR_SCREEN ); if ( total ) { @@ -655,21 +655,21 @@ static void _outputTop( uint32_t total, uint32_t reportLines, struct reportLine dispSamples += report[n].count; totPercent += percentage; - genericsPrintf( C_DATA "%3d.%02d%% " C_SUPPORT " %7" PRIu64 " ", percentage / 100, percentage % 100, report[n].count ); + genericsFPrintf( stdout, C_DATA "%3d.%02d%% " C_SUPPORT " %7" PRIu64 " ", percentage / 100, percentage % 100, report[n].count ); if ( ( options.reportFilenames ) && ( report[n].n->fileindex != NO_FILE ) ) { - genericsPrintf( C_CONTEXT "%s" C_RESET "::", SymbolFilename( _r.s, report[n].n->fileindex ) ); + genericsFPrintf( stdout, C_CONTEXT "%s" C_RESET "::", SymbolFilename( _r.s, report[n].n->fileindex ) ); } if ( ( options.lineDisaggregation ) && ( report[n].n->line ) ) { - genericsPrintf( C_SUPPORT2 "%s" C_RESET "::" C_CONTEXT "%d" EOL, d ? d : SymbolFunction( _r.s, report[n].n->functionindex ), report[n].n->line ); + genericsFPrintf( stdout, C_SUPPORT2 "%s" C_RESET "::" C_CONTEXT "%d" EOL, d ? d : SymbolFunction( _r.s, report[n].n->functionindex ), report[n].n->line ); } else { - genericsPrintf( C_SUPPORT2 "%s" C_RESET EOL, d ? d : SymbolFunction( _r.s, report[n].n->functionindex ) ); + genericsFPrintf( stdout, C_SUPPORT2 "%s" C_RESET EOL, d ? d : SymbolFunction( _r.s, report[n].n->functionindex ) ); } printed++; @@ -709,9 +709,9 @@ static void _outputTop( uint32_t total, uint32_t reportLines, struct reportLine } } - genericsPrintf( C_RESET "-----------------" EOL ); + genericsFPrintf( stdout, C_RESET "-----------------" EOL ); - genericsPrintf( C_DATA "%3d.%02d%% " C_SUPPORT " %7" PRIu64 " " C_RESET "of "C_DATA" %" PRIu64 " "C_RESET" Samples" EOL, totPercent / 100, totPercent % 100, dispSamples, samples ); + genericsFPrintf( stdout, C_DATA "%3d.%02d%% " C_SUPPORT " %7" PRIu64 " " C_RESET "of "C_DATA" %" PRIu64 " "C_RESET" Samples" EOL, totPercent / 100, totPercent % 100, dispSamples, samples ); if ( p ) { @@ -732,13 +732,13 @@ static void _outputTop( uint32_t total, uint32_t reportLines, struct reportLine if ( _r.dwt_event_acc[i] ) { havePrinted = true; - genericsPrintf( "%4s:" C_DATA "%7d " C_RESET, evName[i], _r.dwt_event_acc[i] ); + genericsFPrintf( stdout, "%4s:" C_DATA "%7d " C_RESET, evName[i], _r.dwt_event_acc[i] ); } } if ( havePrinted ) { - genericsPrintf( EOL ); + genericsFPrintf( stdout, EOL ); } if ( options.outputExceptions ) @@ -746,11 +746,11 @@ static void _outputTop( uint32_t total, uint32_t reportLines, struct reportLine /* Tidy up screen output */ while ( printed++ <= options.cutscreen ) { - genericsPrintf( EOL ); + genericsFPrintf( stdout, EOL ); } - genericsPrintf( EOL " Exception | Count | MaxD | TotalTicks | %% | AveTicks | minTicks | maxTicks | maxWall " EOL ); - genericsPrintf( /**/"-------------------+----------+-------+-------------+-------+------------+------------+------------+----------" EOL ); + genericsFPrintf( stdout, EOL " Exception | Count | MaxD | TotalTicks | %% | AveTicks | minTicks | maxTicks | maxWall " EOL ); + genericsFPrintf( stdout, /**/"-------------------+----------+-------+-------------+-------+------------+------------+------------+----------" EOL ); for ( uint32_t e = 0; e < MAX_EXCEPTIONS; e++ ) { @@ -769,26 +769,26 @@ static void _outputTop( uint32_t total, uint32_t reportLines, struct reportLine } const float util_percent = ( float )_r.er[e].totalTime / ( _r.timeStamp - _r.lastReportTicks ) * 100.0f; - genericsPrintf( C_DATA "%3" PRId32 " %-14s" C_RESET " | " C_DATA "%8" PRIu64 C_RESET " |" C_DATA " %5" - PRIu32 C_RESET " | "C_DATA " %9" PRIu64 C_RESET " |" C_DATA "%6.1f" C_RESET " | " C_DATA "%9" PRIu64 C_RESET " | " C_DATA "%9" PRIu64 C_RESET " | " C_DATA" %9" PRIu64 C_RESET " | " C_DATA "%9" - PRIu64 C_RESET EOL, - e, exceptionName, _r.er[e].visits, _r.er[e].maxDepth, _r.er[e].totalTime, util_percent, _r.er[e].totalTime / _r.er[e].visits, _r.er[e].minTime, _r.er[e].maxTime, _r.er[e].maxWallTime ); + genericsFPrintf( stdout, C_DATA "%3" PRId32 " %-14s" C_RESET " | " C_DATA "%8" PRIu64 C_RESET " |" C_DATA " %5" + PRIu32 C_RESET " | "C_DATA " %9" PRIu64 C_RESET " |" C_DATA "%6.1f" C_RESET " | " C_DATA "%9" PRIu64 C_RESET " | " C_DATA "%9" PRIu64 C_RESET " | " C_DATA" %9" PRIu64 C_RESET " | " C_DATA "%9" + PRIu64 C_RESET EOL, + e, exceptionName, _r.er[e].visits, _r.er[e].maxDepth, _r.er[e].totalTime, util_percent, _r.er[e].totalTime / _r.er[e].visits, _r.er[e].minTime, _r.er[e].maxTime, _r.er[e].maxWallTime ); } } } - genericsPrintf( EOL C_RESET "[%s%s%s%s" C_RESET "] ", - ( _r.ITMoverflows != ITMDecoderGetStats( &_r.i )->overflow ) ? C_OVF_IND "V" : C_RESET "-", - ( _r.SWPkt != ITMDecoderGetStats( &_r.i )->SWPkt ) ? C_SOFT_IND "S" : C_RESET "-", - ( _r.TSPkt != ITMDecoderGetStats( &_r.i )->TSPkt ) ? C_TSTAMP_IND "T" : C_RESET "-", - ( _r.HWPkt != ITMDecoderGetStats( &_r.i )->HWPkt ) ? C_HW_IND "H" : C_RESET "-" ); + genericsFPrintf( stdout, EOL C_RESET "[%s%s%s%s" C_RESET "] ", + ( _r.ITMoverflows != ITMDecoderGetStats( &_r.i )->overflow ) ? C_OVF_IND "V" : C_RESET "-", + ( _r.SWPkt != ITMDecoderGetStats( &_r.i )->SWPkt ) ? C_SOFT_IND "S" : C_RESET "-", + ( _r.TSPkt != ITMDecoderGetStats( &_r.i )->TSPkt ) ? C_TSTAMP_IND "T" : C_RESET "-", + ( _r.HWPkt != ITMDecoderGetStats( &_r.i )->HWPkt ) ? C_HW_IND "H" : C_RESET "-" ); if ( ( _r.lastReportTicks ) && ( lastTime != _r.lastReportus ) ) - genericsPrintf( "Interval = " C_DATA "%" PRIu64 "ms " C_RESET "/ "C_DATA "%" PRIu64 C_RESET " (~" C_DATA "%" PRIu64 C_RESET " Ticks/ms)" EOL, - ( ( lastTime - _r.lastReportus ) ) / 1000, _r.timeStamp - _r.lastReportTicks, ( ( _r.timeStamp - _r.lastReportTicks ) * 1000 ) / ( lastTime - _r.lastReportus ) ); + genericsFPrintf( stdout, "Interval = " C_DATA "%" PRIu64 "ms " C_RESET "/ "C_DATA "%" PRIu64 C_RESET " (~" C_DATA "%" PRIu64 C_RESET " Ticks/ms)" EOL, + ( ( lastTime - _r.lastReportus ) ) / 1000, _r.timeStamp - _r.lastReportTicks, ( ( _r.timeStamp - _r.lastReportTicks ) * 1000 ) / ( lastTime - _r.lastReportus ) ); else { - genericsPrintf( C_RESET "Interval = " C_DATA "%" PRIu64 C_RESET "ms" EOL, ( ( lastTime - _r.lastReportus ) ) / 1000 ); + genericsFPrintf( stdout, C_RESET "Interval = " C_DATA "%" PRIu64 C_RESET "ms" EOL, ( ( lastTime - _r.lastReportus ) ) / 1000 ); } genericsReport( V_INFO, " Ovf=%3d ITMSync=%3d ITMErrors=%3d" EOL, @@ -918,38 +918,38 @@ void _itmPumpProcess( uint8_t c ) void _printHelp( const char *const progName ) { - genericsPrintf( "Usage: %s [options]" EOL, progName ); - genericsPrintf( " -c, --cut-after: Cut screen output after number of lines" EOL ); - genericsPrintf( " -D, --no-demangle: Switch off C++ symbol demangling" EOL ); - genericsPrintf( " -d, --del-prefix: to take off front of filenames" EOL ); - genericsPrintf( " -e, --elf-file: to use for symbols" EOL ); - genericsPrintf( " -E, --exceptions: Include exceptions in output report" EOL ); - genericsPrintf( " -f, --input-file: Take input from specified file" EOL ); - genericsPrintf( " -g, --record-file: append historic records to specified file" EOL ); - genericsPrintf( " -h, --help: This help" EOL ); - genericsPrintf( " -I, --interval: Display interval in milliseconds (defaults to %dms)" EOL, TOP_UPDATE_INTERVAL ); - genericsPrintf( " -j, --json-file: Output to file in JSON format (or screen if is '-')" EOL ); - genericsPrintf( " -l, --agg-lines: Aggregate per line rather than per function" EOL ); - genericsPrintf( " -M, --no-colour: Supress colour in output" EOL ); - genericsPrintf( " -n, --itm-sync: Enforce sync requirement for ITM (i.e. ITM needs to issue syncs)" EOL ); - genericsPrintf( " -o, --output-file: to be used for output live file" EOL ); - genericsPrintf( " -O, --objdump-opts: Options to pass directly to objdump" EOL ); - genericsPrintf( " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ITM" EOL ); - genericsPrintf( " -P, --pace: delay in block of data transmission to clients" EOL ); - genericsPrintf( " -r, --routines: to record in live file (default %d routines)" EOL, options.maxRoutines ); - genericsPrintf( " -R, --report-files: Report filenames as part of function discriminator" EOL ); - genericsPrintf( " -s, --server: : to use" EOL ); - genericsPrintf( " -t, --tag: Which OFLOW tag to use (normally 1)" EOL ); - genericsPrintf( " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); - genericsPrintf( " -V, --version: Print version and exit" EOL ); - genericsPrintf( EOL "Environment Variables;" EOL ); - genericsPrintf( " OBJDUMP: to use non-standard obbdump binary" EOL ); + genericsFPrintf( stderr, "Usage: %s [options]" EOL, progName ); + genericsFPrintf( stderr, " -c, --cut-after: Cut screen output after number of lines" EOL ); + genericsFPrintf( stderr, " -D, --no-demangle: Switch off C++ symbol demangling" EOL ); + genericsFPrintf( stderr, " -d, --del-prefix: to take off front of filenames" EOL ); + genericsFPrintf( stderr, " -e, --elf-file: to use for symbols" EOL ); + genericsFPrintf( stderr, " -E, --exceptions: Include exceptions in output report" EOL ); + genericsFPrintf( stderr, " -f, --input-file: Take input from specified file" EOL ); + genericsFPrintf( stderr, " -g, --record-file: append historic records to specified file" EOL ); + genericsFPrintf( stderr, " -h, --help: This help" EOL ); + genericsFPrintf( stderr, " -I, --interval: Display interval in milliseconds (defaults to %dms)" EOL, TOP_UPDATE_INTERVAL ); + genericsFPrintf( stderr, " -j, --json-file: Output to file in JSON format (or screen if is '-')" EOL ); + genericsFPrintf( stderr, " -l, --agg-lines: Aggregate per line rather than per function" EOL ); + genericsFPrintf( stderr, " -M, --no-colour: Supress colour in output" EOL ); + genericsFPrintf( stderr, " -n, --itm-sync: Enforce sync requirement for ITM (i.e. ITM needs to issue syncs)" EOL ); + genericsFPrintf( stderr, " -o, --output-file: to be used for output live file" EOL ); + genericsFPrintf( stderr, " -O, --objdump-opts: Options to pass directly to objdump" EOL ); + genericsFPrintf( stderr, " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ITM" EOL ); + genericsFPrintf( stderr, " -P, --pace: delay in block of data transmission to clients" EOL ); + genericsFPrintf( stderr, " -r, --routines: to record in live file (default %d routines)" EOL, options.maxRoutines ); + genericsFPrintf( stderr, " -R, --report-files: Report filenames as part of function discriminator" EOL ); + genericsFPrintf( stderr, " -s, --server: : to use" EOL ); + genericsFPrintf( stderr, " -t, --tag: Which OFLOW tag to use (normally 1)" EOL ); + genericsFPrintf( stderr, " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); + genericsFPrintf( stderr, " -V, --version: Print version and exit" EOL ); + genericsFPrintf( stderr, EOL "Environment Variables;" EOL ); + genericsFPrintf( stderr, " OBJDUMP: to use non-standard obbdump binary" EOL ); } // ==================================================================================================== void _printVersion( void ) { - genericsPrintf( "orbtop version " GIT_DESCRIBE EOL ); + genericsFPrintf( stderr, "orbtop version " GIT_DESCRIBE EOL ); } // ==================================================================================================== static struct option _longOptions[] = @@ -1395,7 +1395,7 @@ int main( int argc, char *argv[] ) if ( ( !options.json ) || ( options.json[0] != '-' ) ) { - genericsPrintf( CLEAR_SCREEN "Connected..." EOL ); + genericsFPrintf( stderr, CLEAR_SCREEN "Connected..." EOL ); } /* ...just in case we have any readings from a previous incantation */ diff --git a/Src/orbtrace.c b/Src/orbtrace.c index c4b0e1b0..63e83909 100644 --- a/Src/orbtrace.c +++ b/Src/orbtrace.c @@ -137,36 +137,36 @@ static void _intHandler( int sig ) static void _printHelp( const char *const progName ) { - genericsPrintf( "Usage: %s [options]" EOL, progName ); - genericsPrintf( " -a, --serial-speed: to use (when SWO UART is selected)" EOL ); - genericsPrintf( " -e, --power: , Enable or Disable power. Ch is vtref, vtpwr or all" EOL ); - genericsPrintf( " -h, --help:: This help" EOL ); - genericsPrintf( " -l, --list: Show all OrbTrace devices attached to system" EOL ); - genericsPrintf( " -M, --no-colour: Supress colour in output" EOL ); - genericsPrintf( " -T, --trace-format: Trace format; 1,2 or 4 bit parallel with TPIU decode," EOL \ - " m for Manchester SWO, u=UART SWO," EOL \ - " M for Manchester SWO+TPIU, U=UART SWO+TPIU" EOL ); - genericsPrintf( " -n, --serial-number: any part of serial number to differentiate specific OrbTrace device" EOL ); - genericsPrintf( " -p, --voltage: , Set voltage in V, Ch is vtref or vtpwr" EOL ); - genericsPrintf( " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); - genericsPrintf( " -V, --version: Print version and exit" EOL ); - - // genericsPrintf( " *-b: Set default brightness of output leds" EOL ); - // genericsPrintf( " *-F: Force voltage setting" EOL ); - // genericsPrintf( " *-j: Format output in JSON" EOL ); - // genericsPrintf( " *-L: Lock device (prevent further changes)" EOL ); - // genericsPrintf( " *-N: Specify nickname for adaptor (8 chars max)" EOL ); - // genericsPrintf( " *-q: Query all data from connected device" EOL ); - // genericsPrintf( " *-Q: Query specified data from connected device (pPrR VPwr/IPwr/VRef/IRef)" EOL ); - // genericsPrintf( " *-U: Unlock device (allow changes, default state)" EOL ); - // genericsPrintf( " *-w: Write parameters specified on command line to NVRAM" EOL ); - // genericsPrintf( " *-W: Reset all NVRAM parameters to default values" EOL ); + genericsFPrintf( stderr, "Usage: %s [options]" EOL, progName ); + genericsFPrintf( stderr, " -a, --serial-speed: to use (when SWO UART is selected)" EOL ); + genericsFPrintf( stderr, " -e, --power: , Enable or Disable power. Ch is vtref, vtpwr or all" EOL ); + genericsFPrintf( stderr, " -h, --help:: This help" EOL ); + genericsFPrintf( stderr, " -l, --list: Show all OrbTrace devices attached to system" EOL ); + genericsFPrintf( stderr, " -M, --no-colour: Supress colour in output" EOL ); + genericsFPrintf( stderr, " -T, --trace-format: Trace format; 1,2 or 4 bit parallel with TPIU decode," EOL \ + " m for Manchester SWO, u=UART SWO," EOL \ + " M for Manchester SWO+TPIU, U=UART SWO+TPIU" EOL ); + genericsFPrintf( stderr, " -n, --serial-number: any part of serial number to differentiate specific OrbTrace device" EOL ); + genericsFPrintf( stderr, " -p, --voltage: , Set voltage in V, Ch is vtref or vtpwr" EOL ); + genericsFPrintf( stderr, " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); + genericsFPrintf( stderr, " -V, --version: Print version and exit" EOL ); + + // genericsFPrintf( stderr, " *-b: Set default brightness of output leds" EOL ); + // genericsFPrintf( stderr, " *-F: Force voltage setting" EOL ); + // genericsFPrintf( stderr, " *-j: Format output in JSON" EOL ); + // genericsFPrintf( stderr, " *-L: Lock device (prevent further changes)" EOL ); + // genericsFPrintf( stderr, " *-N: Specify nickname for adaptor (8 chars max)" EOL ); + // genericsFPrintf( stderr, " *-q: Query all data from connected device" EOL ); + // genericsFPrintf( stderr, " *-Q: Query specified data from connected device (pPrR VPwr/IPwr/VRef/IRef)" EOL ); + // genericsFPrintf( stderr, " *-U: Unlock device (allow changes, default state)" EOL ); + // genericsFPrintf( stderr, " *-w: Write parameters specified on command line to NVRAM" EOL ); + // genericsFPrintf( stderr, " *-W: Reset all NVRAM parameters to default values" EOL ); } // ==================================================================================================== void _printVersion( void ) { - genericsPrintf( "Orbtrace version " GIT_DESCRIBE ); + genericsFPrintf( stderr, "Orbtrace version " GIT_DESCRIBE ); } // ==================================================================================================== static struct option _longOptions[] = @@ -416,7 +416,7 @@ static int _processOptions( struct RunTime *r, int argc, char *argv[] ) case 'V': /* Print the version of this utility, and schedule to get the version of the probes */ _printVersion(); - genericsPrintf( EOL "Attached Probe(s);" EOL ); + genericsFPrintf( stderr, EOL "Attached Probe(s);" EOL ); _set_action( r, ACTION_LIST_DEVICES ); break; diff --git a/Src/orbtraceIf.c b/Src/orbtraceIf.c index 602e4d80..226b0120 100644 --- a/Src/orbtraceIf.c +++ b/Src/orbtraceIf.c @@ -402,14 +402,14 @@ void OrbtraceIfListDevices( struct OrbtraceIf *o ) char printConstruct[SCRATCH_STRINGLEN]; /* Get longest line */ - genericsPrintf( C_RESET " Id | Description | Serial | Version" EOL ); - genericsPrintf( " ---+---------------------------------------------------+------------------+----------------------------" EOL ); + genericsFPrintf( stderr, C_RESET " Id | Description | Serial | Version" EOL ); + genericsFPrintf( stderr, " ---+---------------------------------------------------+------------------+----------------------------" EOL ); for ( int i = 0; i < o->numDevices; i++ ) { snprintf( printConstruct, MAX_DESC_FIELDLEN, "%s %s", OrbtraceIfGetManufacturer( o, i ), OrbtraceIfGetProduct( o, i ) ) ; - genericsPrintf( C_SEL " %2d " C_RESET "|"C_ELEMENT" %-49s "C_RESET"|"C_ELEMENT" %16s "C_RESET"|"C_ELEMENT" %s" C_RESET EOL, - i + 1, printConstruct, OrbtraceIfGetSN( o, i ), OrbtraceIfGetVersion( o, i ) ); + genericsFPrintf( stderr, C_SEL " %2d " C_RESET "|"C_ELEMENT" %-49s "C_RESET"|"C_ELEMENT" %16s "C_RESET"|"C_ELEMENT" %s" C_RESET EOL, + i + 1, printConstruct, OrbtraceIfGetSN( o, i ), OrbtraceIfGetVersion( o, i ) ); } } @@ -427,7 +427,7 @@ int OrbtraceIfSelectDevice( struct OrbtraceIf *o ) while ( ( selection < 1 ) || ( selection > o->numDevices ) ) { - genericsPrintf( EOL C_SEL "Selection>" C_RESET ); + genericsFPrintf( stderr, EOL C_SEL "Selection>" C_RESET ); scanf( "%d", &selection ); } } diff --git a/Src/orbuculum.c b/Src/orbuculum.c index 93caaf4a..316ab22e 100644 --- a/Src/orbuculum.c +++ b/Src/orbuculum.c @@ -351,41 +351,41 @@ static void _intHandler( int sig ) void _printHelp( const char *const progName, struct RunTime *r ) { - genericsPrintf( "Usage: %s [options]" EOL, progName ); - genericsPrintf( " -a, --serial-speed: to use" EOL ); - genericsPrintf( " -E, --eof: When reading from file, terminate at end of file" EOL ); - genericsPrintf( " -f, --input-file: Take input from specified file" EOL ); - genericsPrintf( " -h, --help: This help" EOL ); - genericsPrintf( " -l, --listen-port: Listen port for incoming ORBFLOW connections (defaults to %d)" EOL, r->options->listenPort ); - genericsPrintf( " -m, --monitor: Output monitor information about the link at ms, min 500ms" EOL ); - genericsPrintf( " -M, --no-colour: Supress colour in output" EOL ); - genericsPrintf( " -n, --serial-number: any part of serial number to differentiate specific device" EOL ); - genericsPrintf( " -o, --output-file: to be used for dump file" EOL ); - genericsPrintf( " -O, --orbtrace: \"\" run orbtrace with specified options on device connect" EOL ); - genericsPrintf( " -p, --serial-port: to use" EOL ); - genericsPrintf( " -P, --pace: delay in block of data transmission to clients" EOL ); - genericsPrintf( " -s, --server: : to use" EOL ); - genericsPrintf( " -T, --tpiu: Strip TPIU framing from input flows (mostly not relevant)" EOL ); - genericsPrintf( " -t, --tag: Legacy TPIU streams to decode and route (Default %s)" EOL, r->options->channelList ); - genericsPrintf( " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); - genericsPrintf( " -V, --version: Print version, connected usb devices, and exit" EOL ); + genericsFPrintf( stderr, "Usage: %s [options]" EOL, progName ); + genericsFPrintf( stderr, " -a, --serial-speed: to use" EOL ); + genericsFPrintf( stderr, " -E, --eof: When reading from file, terminate at end of file" EOL ); + genericsFPrintf( stderr, " -f, --input-file: Take input from specified file" EOL ); + genericsFPrintf( stderr, " -h, --help: This help" EOL ); + genericsFPrintf( stderr, " -l, --listen-port: Listen port for incoming ORBFLOW connections (defaults to %d)" EOL, r->options->listenPort ); + genericsFPrintf( stderr, " -m, --monitor: Output monitor information about the link at ms, min 500ms" EOL ); + genericsFPrintf( stderr, " -M, --no-colour: Supress colour in output" EOL ); + genericsFPrintf( stderr, " -n, --serial-number: any part of serial number to differentiate specific device" EOL ); + genericsFPrintf( stderr, " -o, --output-file: to be used for dump file" EOL ); + genericsFPrintf( stderr, " -O, --orbtrace: \"\" run orbtrace with specified options on device connect" EOL ); + genericsFPrintf( stderr, " -p, --serial-port: to use" EOL ); + genericsFPrintf( stderr, " -P, --pace: delay in block of data transmission to clients" EOL ); + genericsFPrintf( stderr, " -s, --server: : to use" EOL ); + genericsFPrintf( stderr, " -T, --tpiu: Strip TPIU framing from input flows (mostly not relevant)" EOL ); + genericsFPrintf( stderr, " -t, --tag: Legacy TPIU streams to decode and route (Default %s)" EOL, r->options->channelList ); + genericsFPrintf( stderr, " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); + genericsFPrintf( stderr, " -V, --version: Print version, connected usb devices, and exit" EOL ); } // ==================================================================================================== void _printVersion( struct RunTime *r ) { - genericsPrintf( "orbuculum version " GIT_DESCRIBE EOL ); + genericsFPrintf( stderr, "orbuculum version " GIT_DESCRIBE EOL ); r->o = OrbtraceIfCreateContext(); int ndevices = OrbtraceIfGetDeviceList( r->o, NULL, DEVTYPE( DEVICE_ORBTRACE_MINI ) | DEVTYPE( DEVICE_BMP ) ); if ( !ndevices ) { - genericsPrintf( "No devices found" EOL ); + genericsFPrintf( stderr, "No devices found" EOL ); } else { - genericsPrintf( "Device%s Found;" EOL, ( ndevices > 1 ) ? "s" : "" ); + genericsFPrintf( stderr, "Device%s Found;" EOL, ( ndevices > 1 ) ? "s" : "" ); OrbtraceIfListDevices( r->o ); } @@ -544,6 +544,7 @@ bool _processOptions( int argc, char *argv[], struct RunTime *r ) if ( *a == ':' ) { + *a = 0; r->options->nwserverPort = atoi( ++a ); } @@ -721,19 +722,19 @@ void _checkInterval( void *params ) if ( r->conn ) { - genericsPrintf( C_PREV_LN C_DATA ); + genericsFPrintf( stdout, C_PREV_LN C_DATA ); if ( snapInterval / 1000000 ) { - genericsPrintf( "%4d.%d " C_RESET "MBits/sec ", snapInterval / 1000000, ( snapInterval * 1 / 100000 ) % 10 ); + genericsFPrintf( stdout, "%4d.%d " C_RESET "MBits/sec ", snapInterval / 1000000, ( snapInterval * 1 / 100000 ) % 10 ); } else if ( snapInterval / 1000 ) { - genericsPrintf( "%4d.%d " C_RESET "KBits/sec ", snapInterval / 1000, ( snapInterval / 100 ) % 10 ); + genericsFPrintf( stdout, "%4d.%d " C_RESET "KBits/sec ", snapInterval / 1000, ( snapInterval / 100 ) % 10 ); } else { - genericsPrintf( " %4d " C_RESET " Bits/sec ", snapInterval ); + genericsFPrintf( stdout, " %4d " C_RESET " Bits/sec ", snapInterval ); } uint64_t totalPct = 0; @@ -755,11 +756,11 @@ void _checkInterval( void *params ) { if ( ( !r->tagCount[i].hasHandler ) && r->options->useTPIU ) { - genericsPrintf( C_NOCHAN" [%d:" "%3d%%] " C_RESET, i, w / 10 ); + genericsFPrintf( stdout, C_NOCHAN" [%d:" "%3d%%] " C_RESET, i, w / 10 ); } else { - genericsPrintf( " %d:" C_DATA"%3d%% " C_RESET, i, w / 10 ); + genericsFPrintf( stdout, " %d:" C_DATA"%3d%% " C_RESET, i, w / 10 ); } } @@ -767,18 +768,18 @@ void _checkInterval( void *params ) } w = ( totalPct < 1000 ) ? 1000 - totalPct : 0; - genericsPrintf( " Waste:" C_DATA "%2d.%01d%% " C_RESET, w / 10, w % 10 ); + genericsFPrintf( stdout, " Waste:" C_DATA "%2d.%01d%% " C_RESET, w / 10, w % 10 ); } if ( r->options->dataSpeed > 100 ) { /* Conversion to percentage done as a division to avoid overflow */ uint32_t fullPercent = ( snapInterval * 100 ) / r->options->dataSpeed; - genericsPrintf( "(" C_DATA " %3d%% " C_RESET "full)", ( fullPercent > 100 ) ? 100 : fullPercent ); + genericsFPrintf( stdout, "(" C_DATA " %3d%% " C_RESET "full)", ( fullPercent > 100 ) ? 100 : fullPercent ); } genericsReport( V_INFO, "Ce=%d Oe=%d", OFLOWGetCOBSErrors( &_r.oflow ), OFLOWGetErrors( &_r.oflow ) ); - genericsPrintf( " " C_RESET C_CLR_LN EOL ); + genericsFPrintf( stdout, " " C_RESET C_CLR_LN EOL ); } r->intervalRawBytes = 0; @@ -1612,7 +1613,7 @@ int main( int argc, char *argv[] ) } /* Blank line for tidyness' sake */ - genericsPrintf( EOL ); + genericsFPrintf( stdout, EOL ); if ( ( _r.options->nwserverPort ) || ( _r.options->port ) || ( _r.options->file ) ) { diff --git a/Src/orbzmq.c b/Src/orbzmq.c index a83030ae..a18e6b99 100644 --- a/Src/orbzmq.c +++ b/Src/orbzmq.c @@ -414,32 +414,32 @@ void _itmPumpProcess( char c ) void _printHelp( const char *const progName ) { - genericsPrintf( "Usage: %s [options]" EOL, progName ); - genericsPrintf( " -c, --channel: ,, of channel to populate (repeat per channel)" EOL ); - genericsPrintf( " -e, --hwevent: Comma-separated list of published hwevents" EOL ); - genericsPrintf( " -E, --eof: Terminate when the file/socket ends/is closed, otherwise wait to reconnect" EOL ); - genericsPrintf( " -f, --input-file: Take input from specified file" EOL ); - genericsPrintf( " -h, --help: This help" EOL ); - genericsPrintf( " -M, --no-colour: Supress colour in output" EOL ); - genericsPrintf( " -n, --itm-sync: Enforce sync requirement for ITM (i.e. ITM needs to issue syncs)" EOL ); - genericsPrintf( " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ITM" EOL ); - genericsPrintf( " -s, --server: : to use, default %s:%d" EOL, options.server, options.port ); - genericsPrintf( " -t, --tag: : Which Orbflow tag to use (normally 1)" EOL ); - genericsPrintf( " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); - genericsPrintf( " -V, --version: Print version and exit" EOL ); - genericsPrintf( " -z, --zbind: : ZeroMQ bind URL, default %s" EOL, options.bindUrl ); - genericsPrintf( EOL ); - genericsPrintf( "Available HW events: " EOL ); - genericsPrintf( " all - All hwevents TS - Timestamp" EOL ); - genericsPrintf( " EXCP - Exception entry/exit PC - PC sampling" EOL ); - genericsPrintf( " DWT - DWT event RWWT - Read/write watchpoint" EOL ); - genericsPrintf( " AWP - Access watchpoint OFS - Data offset" EOL ); + genericsFPrintf( stderr, "Usage: %s [options]" EOL, progName ); + genericsFPrintf( stderr, " -c, --channel: ,, of channel to populate (repeat per channel)" EOL ); + genericsFPrintf( stderr, " -e, --hwevent: Comma-separated list of published hwevents" EOL ); + genericsFPrintf( stderr, " -E, --eof: Terminate when the file/socket ends/is closed, otherwise wait to reconnect" EOL ); + genericsFPrintf( stderr, " -f, --input-file: Take input from specified file" EOL ); + genericsFPrintf( stderr, " -h, --help: This help" EOL ); + genericsFPrintf( stderr, " -M, --no-colour: Supress colour in output" EOL ); + genericsFPrintf( stderr, " -n, --itm-sync: Enforce sync requirement for ITM (i.e. ITM needs to issue syncs)" EOL ); + genericsFPrintf( stderr, " -p, --protocol: Protocol to communicate. Defaults to OFLOW if -s is not set, otherwise ITM" EOL ); + genericsFPrintf( stderr, " -s, --server: : to use, default %s:%d" EOL, options.server, options.port ); + genericsFPrintf( stderr, " -t, --tag: : Which Orbflow tag to use (normally 1)" EOL ); + genericsFPrintf( stderr, " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); + genericsFPrintf( stderr, " -V, --version: Print version and exit" EOL ); + genericsFPrintf( stderr, " -z, --zbind: : ZeroMQ bind URL, default %s" EOL, options.bindUrl ); + genericsFPrintf( stderr, EOL ); + genericsFPrintf( stderr, "Available HW events: " EOL ); + genericsFPrintf( stderr, " all - All hwevents TS - Timestamp" EOL ); + genericsFPrintf( stderr, " EXCP - Exception entry/exit PC - PC sampling" EOL ); + genericsFPrintf( stderr, " DWT - DWT event RWWT - Read/write watchpoint" EOL ); + genericsFPrintf( stderr, " AWP - Access watchpoint OFS - Data offset" EOL ); } // ==================================================================================================== void _printVersion( void ) { - genericsPrintf( "orbcat version " GIT_DESCRIBE EOL ); + genericsFPrintf( stderr, "orbcat version " GIT_DESCRIBE EOL ); } static int32_t _parseHWEventsArg( char *s ) diff --git a/Support/60-orbcode.rules b/Support/60-orbcode.rules index 1501072c..a32ba006 100644 --- a/Support/60-orbcode.rules +++ b/Support/60-orbcode.rules @@ -4,9 +4,9 @@ ACTION!="add|change|bind", GOTO="orb_rules_end" SUBSYSTEM!="usb|tty|hidraw", GOTO="orb_rules_end" -# Orbrace mini in bootloader mode -ATTRS{idVendor}=="1209" ATTRS{idProduct}=="3442", GROUP="plugdev", TAG+="uaccess" -# Orbrace mini -ATTRS{idVendor}=="1209" ATTRS{idProduct}=="3443", GROUP="plugdev", TAG+="uaccess" +# Orbtrace mini in bootloader mode +ATTRS{idVendor}=="1209", ATTRS{idProduct}=="3442", GROUP="plugdev", TAG+="uaccess" +# Orbtrace mini +ATTRS{idVendor}=="1209", ATTRS{idProduct}=="3443", GROUP="plugdev", TAG+="uaccess" LABEL="orb_rules_end" diff --git a/Support/gdbtrace.init b/Support/gdbtrace.init index 0eb38c26..fc0c8513 100644 --- a/Support/gdbtrace.init +++ b/Support/gdbtrace.init @@ -81,8 +81,8 @@ end # Definitions for the CPU types we currently support set $CPU_IMXRT102X=1 -set $CPU_STM32=2 set $CPU_IMXRT106X=1 +set $CPU_STM32F1F4F7=2 set $CPU_NRF=3 set $CPU_EFR32=4 set $CPU_TM4C=5 @@ -91,6 +91,7 @@ set $CPU_IMXRT117X=7 set $CPU_KINETIS=8 set $CPU_SAMD5x=9 set $CPU_STM32M33=10 +set $CPU_STM32H7=11 # ==================================================================== set $CDBBASE=0xE000EDF0 @@ -100,16 +101,61 @@ set $TPIUBASE=0xE0040000 set $ETMBASE=0xE0041000 set $CTIBASE=0xE0042000 +define setTRCENA + set *($CDBBASE+0xC)|=(1<<24) +end +document setTRCENA +setTRCENA Enables trace peripherals (DWT,ITM,ETM) in DEMCR. +end + +define unlockComponent + set *($arg0 + 0xfb0) = 0xc5acce55 +end + define _setAddressesSTM32 # Locations in the memory map for interesting things on STM32 - if ($CPU == $CPU_STM32M33) - set $RCCBASE = 0x46020c00 - set $GPIOBASE = 0x42020000 - set $DBGMCUBASE = 0xE0044000 + + set $dev = $arg0 + + if ! $dev + # Device type not specified, detect from DBGMCU ID register. + if (*0x5C001000 & 0x7ff) == 0x450 + set $CPU = $CPU_STM32H7 + else + set $CPU = $CPU_STM32F1F4F7 + end else - set $RCCBASE = 0x40023800 - set $GPIOBASE = 0x40020000 - set $DBGMCUBASE = 0xE0042000 + if $dev == 33 + set $CPU = $CPU_STM32M33 + end + if ($dev == 1) || ($dev == 4) || ($dev == 7) + set $CPU = $CPU_STM32F1F4F7 + end + end + + if $CPU == $CPU_STM32M33 + set $GPIOBASE = 0x42020000 + set $RCCGPIO = 0x46020c8c + set $DBGMCU_CR = 0xE0044004 + end + + if $CPU == $CPU_STM32H7 + set $GPIOBASE = 0x58020000 + set $RCCGPIO = 0x580244E0 + set $DBGMCU_CR = 0x5C001004 + set $SWOBASE = 0x5C003000 + set $SWTFBASE = 0x5C004000 + set $CSTFBASE = 0x5C013000 + set $ETFBASE = 0x5C014000 + set $TPIUBASE = 0x5C015000 + end + + if $CPU == $CPU_STM32F1F4F7 + set $GPIOBASE = 0x40020000 + set $RCCGPIO = 0x40023830 + set $DBGMCU_CR = 0xE0042004 + set $RRCGPIO = 0x40023830 + end end define _setAddressesIMXRT @@ -272,12 +318,12 @@ define _setupTraceBusS32K344 end # Enable access to the funnels and ETFs. - set *($FUNNEL_0_BASE + 0xfb0) = 0xc5acce55 - set *($FUNNEL_1_BASE + 0xfb0) = 0xc5acce55 - set *($FUNNEL_2_BASE + 0xfb0) = 0xc5acce55 - set *($ETF_CM7_CLUSTER_ETMI_BASE + 0xfb0) = 0xc5acce55 - set *($ETF_CM7_CLUSTER_ETMD_BASE + 0xfb0) = 0xc5acce55 - set *($ETF_SHARED_SYSTEM_BASE + 0xfb0) = 0xc5acce55 + unlockComponent $FUNNEL_0_BASE + unlockComponent $FUNNEL_1_BASE + unlockComponent $FUNNEL_2_BASE + unlockComponent $ETF_CM7_CLUSTER_ETMI_BASE + unlockComponent $ETF_CM7_CLUSTER_ETMD_BASE + unlockComponent $ETF_SHARED_SYSTEM_BASE # Enable all inputs of all funnels to ensure that all trace sources # can pass. Enabling all inputs is probably not optimal, so this @@ -361,7 +407,7 @@ end define _startETMv35 # Allow access to device - set *($ETMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ETMBASE # Enter configuration mode (write twice to be sure we reached it) set *($ETMBASE) = (1<<10) @@ -591,34 +637,43 @@ define prepareSWO end # Make sure we can get to everything - set *($ITMBASE+0xfb0) = 0xc5acce55 - set *($ETMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ITMBASE + unlockComponent $DWTBASE - set *($CDBBASE+0xC)|=(1<<24) + set $_formatterPresent=1 + set $_protocolBase=$TPIUBASE + if $CPU == $CPU_STM32H7 + set $_formatterPresent=0 + set $_protocolBase=$SWOBASE + unlockComponent $SWOBASE + end + + setTRCENA if ($useMan==0) # Use Async mode pin protocol (TPIU_SPPR) - set *($TPIUBASE+0xF0) = 2 + set *($_protocolBase+0xF0) = 2 else # Use Manchester mode pin protocol (TPIU_SPPR) - set *($TPIUBASE+0xF0) = 1 + set *($_protocolBase+0xF0) = 1 # There are two edges in a bit, so double the clock set $speed = $speed*2 end # Output bits at speed dependent on system clock - set *($TPIUBASE+0x10) = ((($clockspeed+$speed-1)/$speed)-1) + set *($_protocolBase+0x10) = ((($clockspeed+$speed-1)/$speed)-1) - if ($useTPIU==1) - # Use TPIU formatter and flush - set *($TPIUBASE+0x304) = 0x102 - else - set *($TPIUBASE+0x304) = 0x100 + if $_formatterPresent==1 + if $useTPIU==1 + # Use TPIU formatter and flush + set *($TPIUBASE+0x304) = 0x102 + else + set *($TPIUBASE+0x304) = 0x100 + end end # Flush all initial configuration - set *($CDBBASE+0xC)|=(1<<24) set *($DWTBASE) = 0 set *($ITMBASE+0xe80) = 0 @@ -846,10 +901,10 @@ define enableIMXRT117XSWO _setAddressesIMXRT117X # Configure trace funnels/ATB. - set *($FUNNEL_CSSYS_BASE + 0xfb0) = 0xc5acce55 + unlockComponent $FUNNEL_CSSYS_BASE set *($FUNNEL_CSSYS_BASE) |= 0xff - set *($FUNNEL_M7_BASE + 0xfb0) = 0xc5acce55 + unlockComponent $FUNNEL_M7_BASE set *($FUNNEL_M7_BASE) |= 0xff # TODO: configure trace subsystem clocks. @@ -859,7 +914,7 @@ define enableIMXRT117XSWO set *(0x40c0806c) = 0x2 # Allow access to SWO TPIU registers. - set *($TPIU_SWO_BASE + 0xfb0) = 0xc5acce55 + unlockComponent $TPIU_SWO_BASE # Set $TPIUBASE for use by other commands in this file. set $TPIUBASE = $TPIU_SWO_BASE @@ -867,8 +922,6 @@ define enableIMXRT117XSWO #set language auto end -# ==================================================================== - define enableKinetisSWO _setAddressesKinetis set language c @@ -886,40 +939,52 @@ define enableKinetisSWO set language auto end +# ==================================================================== + define enableSTM32SWO #set language c - set $tgt=1 + set $dev=0 if $argc >= 1 - set $tgt = $arg0 + set $dev = $arg0 + end + _setAddressesSTM32 $dev + + if $CPU == $CPU_STM32H7 + # Set D1DBGCKEN, D3DBGCKEN + set *$DBGMCU_CR |= 7 | (6 << 20) + # Unlock SWO trace funnel. + unlockComponent $SWTFBASE + # Enable port S0 in SWO trace funnel. + set *($SWTFBASE + 0x000) = 0x00000301 + # SWO on PB3 + enableSTM32Pin 1 3 3 end - if ($tgt==33) - set $CPU=$CPU_STM32M33 - else - set $CPU=$CPU_STM32 + if ($CPU == $CPU_STM32F1F4F7) + if (($dev==4) || ($dev==7)) + # STM32F4/7 variant: SWO on PB3. + enableSTM32Pin 1 3 3 + else + # STM32F1 variant. + # RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; + set *0x40021018 |= 1 + # AFIO->MAPR |= (2 << 24); // Disable JTAG to release TRACESWO + set *0x40010004 |= 0x2000000 + end end - _setAddressesSTM32 - if (($tgt==4) || ($tgt==7)) - # STM32F4/7 variant: SWO on PB3. - enableSTM32Pin 1 3 3 - else - # STM32F1 variant. - # RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; - set *0x40021018 |= 1 - # AFIO->MAPR |= (2 << 24); // Disable JTAG to release TRACESWO - set *0x40010004 |= 0x2000000 + if $CPU != $CPU_STM32H7 + # Common initialisation. + # DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; + set *$DBGMCU_CR |= 0x20 end - # Common initialisation. - # DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; - set *($DBGMCUBASE+4) |= 0x20 #set language auto end document enableSTM32SWO enableSTM32SWO Configure output pin on STM32 for SWO use. - : Type of STM32 Device 4=f4, 7=f7, 33=M33 + : Type of STM32 Device 1=f1, 4=f4, 7=f7, 33=M33 end # ==================================================================== define enableSAMD5XSWD @@ -1006,7 +1071,7 @@ end define _doTRACE # Must be called with $bits containing number of bits to set trace for - set *($ITMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ITMBASE # Set port size (TPIU_CSPSR) set *($TPIUBASE+4) = (1<<$bits) @@ -1020,15 +1085,11 @@ end # ==================================================================== define enableSTM32Pin #set language c - _setAddressesSTM32 + set $_GPIOPORT = $GPIOBASE + 0x400 * $arg0 # Enable GPIO port in RCC - if ($CPU == $CPU_STM32M33) - set *($RCCBASE + 0x8c) |= (0x1<<$arg0) - else - set *($RCCBASE + 0x30) |= (0x1<<$arg0) - end + set *($RCCGPIO) |= (0x1<<$arg0) # MODER: Alternate Function set *($_GPIOPORT+0x00) &= ~(0x3<<2*$arg1) @@ -1072,7 +1133,7 @@ define enableSTM32TRACE set $bits=4 set $drive=1 - set $type=1 + set $dev=1 if $argc >= 1 set $bits = $arg0 @@ -1085,8 +1146,8 @@ define enableSTM32TRACE set $drive = $arg1 end - if $type >= 3 - set $drive = $arg2 + if $argc >= 3 + set $dev = $arg2 end if ($drive > 3) @@ -1095,19 +1156,36 @@ define enableSTM32TRACE set $bits = $bits-1 - if ($type==33) - set $CPU=$CPU_STM32M33 - else - set $CPU=$CPU_STM32 - end - _setAddressesSTM32 + _setAddressesSTM32 $dev # Enable Trace TRCENA (DCB DEMCR) needed for clocks - set *($CDBBASE+0xC)=(1<<24) + setTRCENA + + + if ($CPU == $CPU_STM32H7) + # Enable TRACECKEN, D1DBGCKEN + set *$DBGMCU_CR |= 7 | (3 << 20) - # Enable compensation cell - set *0x40023844 |= (1<<14) - set *0x40013820 |=1 + unlockComponent $ETFBASE + unlockComponent $CSTFBASE + unlockComponent $TPIUBASE + + # Hardware FIFO mode + set *($ETFBASE + 0x028) = 2 + # Formatter and flush control + set *($ETFBASE + 0x304) |= 1 + # Enable ETF trace capture + set *($ETFBASE + 0x020) = 1 + + # Enable both ETM and ITM in trace funnel. bit0=ETM, bit1=ITM + set *($CSTFBASE + 0x000) |= 3 + else + if $CPU != $CPU_STM32M33 + # Enable compensation cell + set *($RRCGPIO+0x14) |= (1<<14) + set *0x40013820 |=1 + end + end # Setup PE2 & PE3 enableSTM32Pin 4 2 $drive @@ -1124,20 +1202,29 @@ define enableSTM32TRACE enableSTM32Pin 4 6 $drive end - # Set number of bits in DBGMCU_CR - set *($DBGMCUBASE+4) &= ~(3<<6) + if $CPU != $CPU_STM32H7 + # Set number of bits in DBGMCU_CR + set *$DBGMCU_CR &= ~(3<<6) - if ($bits<3) - set *($DBGMCUBASE+4) |= ((($bits+1)<<6) | (1<<5)) - else - set *$(DBGMCUBASE+4) |= ((3<<6) | (1<<5)) + if ($bits<3) + set *$DBGMCU_CR |= ((($bits+1)<<6) | (1<<5)) + else + set *$DBGMCU_CR |= ((3<<6) | (1<<5)) + end end - # Enable Trace TRCENA (DCB DEMCR) - set *($CDBBASE+0xC)=(1<<24) - # Finally start the trace output - _doTRACE + + # Set port size (TPIU_CURPSIZE) + set *($TPIUBASE+4) = (1<<$bits) + + if $CPU != $CPU_STM32H7 + # Set pin protocol to Sync Trace Port (TPIU_SPPR) + set *($TPIUBASE+0xF0)=0 + end + + # TPIU formatter and flush control register (TPIU_FFCR) + set *($TPIUBASE+0x304) = 0x102 #set language auto end @@ -1183,7 +1270,7 @@ define enableNRF52TRACE # from modules/nrfx/mdk/system_nrf52.c # CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk; - set *($CDBBASE+0xC) |= (1<<24) + setTRCENA # NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Parallel << CLOCK_TRACECONFIG_TRACEMUX_Pos; set *($NRF_CLOCK+0x0000055C) &= ~(3 << 16) @@ -1291,7 +1378,7 @@ define enableNRF53TRACE set *($NRF_TAD_S+0x518) = $cspeed # Enable Trace TRCENA (DCB DEMCR) - set *($CDBBASE+0xC)=(1<<24) + setTRCENA # Finally start the trace output _doTRACE @@ -1383,7 +1470,7 @@ define enableTM4C123TRACE end # Enable Trace TRCENA (DCB DEMCR) - set *($CDBBASE+0xC)=(1<<24) + setTRCENA # Finally start the trace output _doTRACE @@ -1505,7 +1592,7 @@ define enableLPC176xTRACE set *0x4002C028 = (1 << 3) # Enable Trace TRCENA (DCB DEMCR) - set *($CDBBASE+0xC)=(1<<24) + setTRCENA # Start tracing set $bits = $bits-1 @@ -1576,7 +1663,7 @@ define enableSAMD5XTRACE end # Enable Trace TRCENA (DCB DEMCR) - set *($CDBBASE+0xC)=(1<<24) + setTRCENA # Finally start the trace output _doTRACE @@ -1595,7 +1682,7 @@ define dwtPOSTCNT if ($argc!=1) help dwtPOSTCNT else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<22) else @@ -1615,7 +1702,7 @@ define dwtFOLDEVT if ($argc!=1) help dwtFOLDEVT else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<21) else @@ -1635,7 +1722,7 @@ define dwtLSUEVT if ($argc!=1) help dwtLSUEVT else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<20) else @@ -1655,7 +1742,7 @@ define dwtSLEEPEVT if ($argc!=1) help dwtSLEEPEVT else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<19) else @@ -1675,7 +1762,7 @@ define dwtDEVEVT if ($argc!=1) help dwtDEVEVT else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<18) else @@ -1686,7 +1773,7 @@ define dwtDEVEVT #set language auto end document dwtDEVEVT -dwtDEVEVT <0|1> Enable Exception counter overflow event packet generation +dwtDEVEVT <0|1> Enable Exception overhead counter overflow event packet generation end # ==================================================================== define dwtCPIEVT @@ -1695,7 +1782,7 @@ define dwtCPIEVT if ($argc!=1) help dwtCPIEVT else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<17) else @@ -1715,7 +1802,7 @@ define dwtTraceException if ($argc!=1) help dwtTraceException else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<16) else @@ -1735,7 +1822,7 @@ define dwtSamplePC if ($argc!=1) help dwtSamplePC else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<12) else @@ -1755,7 +1842,7 @@ define dwtSyncTap if (($argc!=1) || ($arg0<0) || ($arg0>3)) help dwtSyncTap else - set *($CDBBASE|0xC) |= 0x1000000 + setTRCENA set *($DWTBASE) &= ~(0x03<<10) set *($DWTBASE) |= (($arg0&0x03)<<10) end @@ -1772,7 +1859,7 @@ define dwtPostTap if (($argc!=1) || ($arg0<0) || ($arg0>1)) help dwtPostTap else - set *($CDBBASE|0xC) |= 0x1000000 + setTRCENA if ($arg0==0) set *($DWTBASE) &= ~(1<<9) else @@ -1792,7 +1879,7 @@ define dwtPostInit if (($argc!=1) || ($arg0<0) || ($arg0>15)) help dwtPostInit else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA set *($DWTBASE) &= ~(0x0f<<5) set *($DWTBASE) |= (($arg0&0x0f)<<5) end @@ -1809,7 +1896,7 @@ define dwtPostReset if (($argc!=1) || ($arg0<0) || ($arg0>15)) help dwtPostReset else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA set *($DWTBASE) &= ~(0x0f<<1) set *($DWTBASE) |= (($arg0&0x0f)<<1) end @@ -1828,7 +1915,7 @@ define dwtCycEna if ($argc!=1) help dwtCycEna else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<0) else @@ -1849,7 +1936,7 @@ define ITMId if (($argc!=1) || ($arg0<0) || ($arg0>127)) help ITMId else - set *($ITMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ITMBASE set *($ITMBASE+0xe80) &= ~(0x7F<<16) set *($ITMBASE+0xe80) |= (($arg0&0x7f)<<16) end @@ -1866,7 +1953,7 @@ define ITMGTSFreq if (($argc!=1) || ($arg0<0) || ($arg0>3)) help ITMGTSFreq else - set *($ITMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ITMBASE set *($ITMBASE+0xe80) &= ~(0x3<<10) set *($ITMBASE+0xe80) |= (($arg0&3)<<10) end @@ -1885,7 +1972,7 @@ define ITMTSPrescale if (($argc!=1) || ($arg0<0) || ($arg0>3)) help ITMTSPrescale else - set *($ITMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ITMBASE set *($ITMBASE+0xe80) &= ~(0x3<<8) set *($ITMBASE+0xe80) |= (($arg0&3)<<8) end @@ -1902,7 +1989,7 @@ define ITMSWOEna if (($argc!=1) || ($arg0<0) || ($arg0>1)) help ITMSWOEna else - set *($ITMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ITMBASE if ($arg0==0) set *($ITMBASE+0xe80) &= ~(0x1<<4) else @@ -1923,7 +2010,7 @@ define ITMTXEna if (($argc!=1) || ($arg0<0) || ($arg0>1)) help ITMTXEna else - set *($ITMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ITMBASE if ($arg0==0) set *($ITMBASE+0xe80) &= ~(0x1<<3) else @@ -1944,7 +2031,7 @@ define ITMSYNCEna if (($argc!=1) || ($arg0<0) || ($arg0>1)) help ITMSYNCEna else - set *($ITMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ITMBASE if ($arg0==0) set *($ITMBASE+0xe80) &= ~(0x1<<2) else @@ -1965,7 +2052,7 @@ define ITMTSEna if (($argc!=1) || ($arg0<0) || ($arg0>1)) help ITMTSEna else - set *($ITMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ITMBASE if ($arg0==0) set *($ITMBASE+0xe80) &= ~(0x1<<1) else @@ -1985,7 +2072,7 @@ define ITMEna if (($argc!=1) || ($arg0<0) || ($arg0>1)) help ITMEna else - set *($ITMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ITMBASE if ($arg0==0) set *($ITMBASE+0xe80) &= ~(0x1<<0) else @@ -2005,7 +2092,7 @@ define ITMTER if (($argc!=2) || ($arg0<0) || ($arg0>7)) help ITMTER else - set *($ITMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ITMBASE set *($ITMBASE+0xe00+4*$arg0) = $arg1 end @@ -2021,7 +2108,7 @@ define ITMTPR if ($argc!=1) help ITMTPR else - set *($ITMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ITMBASE set *($ITMBASE+0xe40) = $arg0 end @@ -2037,7 +2124,7 @@ define tracetest if ($argc!=1) help tracetest else - set *($TPIUBASE+0xfb0) = 0xc5acce55 + unlockComponent $TPIUBASE if ($arg0 == 0) set *($TPIUBASE+0x204) = 0 else diff --git a/meson.build b/meson.build index 8b8f6b10..338af476 100644 --- a/meson.build +++ b/meson.build @@ -115,21 +115,6 @@ executable('orbuculum', install: true, ) -if host_machine.system() != 'windows' - executable('orbfifo', - sources: [ - 'Src/orbfifo.c', - 'Src/filewriter.c', - 'Src/itmfifos.c', - git_version_info_h, - ], - include_directories: incdirs, - dependencies: dependencies, - link_with: liborb, - install: true, - ) -endif - executable('orbcat', sources: [ 'Src/orbcat.c',