From 97f1aac065be5bdae2e5359a105335b2117351c7 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Thu, 5 Sep 2024 21:23:29 +0100 Subject: [PATCH 01/46] Update documentation to reflect this is 2.2.0 stablisation --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 32f45296..1c0ef8b3 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ![Screenshot](https://raw.githubusercontent.com/orbcode/orbuculum/main/Docs/title.png) -This (orbflow) is the development branch for V2.2.0. Development is generally done in feature branches and folded into main as those features mature, but the changes in orbflow are significant and disruptive, with limited user visible benefit, so we want to keep them off main for a little while longer. +This is the branch for the development of Orbuculum V2.2.0 which is currently in feature freeze and Beta test. Bugfixes for 2.2.0 will be done in this branch. Development is generally done in feature branches and folded into main as those features mature - that will be post 2.2.0. Version 2.2.0 builds on 2.1.0 and adds several new CPU families, improved client application handling and the start of ETM4 support. Stats and timing are also much improved and the whole communications subsystem has been simplified and streamlined. Most importantly though, we have moved from 'legacy' protocol (basically, the exact same protocol that flows from the chip) for communications to 'orbflow' protocol. Orbflow protocol is an extensible packet oriented protocol which provides a more compact representation of the probe data. By default orbflow is used transparently between orbuculum and client applications. If you have an ORBTrace 1.4.0 or higher version then it is also used for communication from the probe to orbuculum. If you have your own legacy applications, or a version of ORBTrace less that 1.4.0, then the system will fall back to legacy protocol transparently. You can have a hybrid arrangement where some clients use legacy protocol and some use orbflow no problem. As you might imagine this can quickly become complex so please yell up if any edge cases don't seem to work correctly! From 1dd52a6f6ed3dd6389be48bcf15e9e39f05a1047 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Mon, 9 Sep 2024 23:44:03 +0100 Subject: [PATCH 02/46] Report (at higher verbosity levels) when client disconnects --- Src/nwclient.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/Src/nwclient.c b/Src/nwclient.c index 085c7f21..7011374c 100644 --- a/Src/nwclient.c +++ b/Src/nwclient.c @@ -69,7 +69,7 @@ struct nwClient volatile struct nwClient *prevClient; /* Parameters used to run the client */ - int portNo; /* Port of connection */ + int fdNo; /* file descriptor of incoming connection */ }; // ==================================================================================================== @@ -105,7 +105,7 @@ static int _lock_with_timeout( pthread_mutex_t *mutex, const struct timespec *ts static void _clientRemoveNoLock( volatile struct nwClient *c ) { - close( c->portNo ); + close( c->fdNo ); if ( c->prevClient ) { @@ -154,14 +154,14 @@ static void *_listenTask( void *arg ) } inet_ntop( AF_INET, &cli_addr.sin_addr, s, 99 ); - genericsReport( V_INFO, "New connection from %s" EOL, s ); + genericsReport( V_INFO, "New connection from %s index %d" EOL, s, newsockfd ); /* We got a new connection - spawn a record to handle it */ client = ( struct nwClient * )calloc( 1, sizeof( struct nwClient ) ); MEMCHECK( client, NULL ); client->parent = h; - client->portNo = newsockfd; + client->fdNo = newsockfd; /* Make port non-blocking */ #ifdef WIN32 @@ -235,13 +235,14 @@ void nwclientSend( struct nwclientsHandle *h, uint32_t len, const uint8_t *ipbuf while ( t && ( sent >= 0 ) ) { - sent = send( n->portNo, p, t, MSG_NOSIGNAL ); + sent = send( n->fdNo, p, t, MSG_NOSIGNAL ); p += sent; t -= sent; } if ( t ) { + genericsReport( V_INFO, "Killed connection index %d" EOL, n->fdNo ); volatile struct nwClient *newn = n->nextClient; _clientRemoveNoLock( n ); n = newn; From d15cc3e12a87f97f56b1076efc43c418ba8f4456 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Fri, 20 Sep 2024 22:44:09 +0100 Subject: [PATCH 03/46] Add COBS draining state to ensure fast resync --- Inc/cobs.h | 3 ++- Src/cobs.c | 10 +++++++++- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/Inc/cobs.h b/Inc/cobs.h index 2b0827f7..a4199186 100644 --- a/Inc/cobs.h +++ b/Inc/cobs.h @@ -26,7 +26,8 @@ extern "C" { enum COBSPumpState { COBS_IDLE, - COBS_RXING + COBS_RXING, + COBS_DRAINING }; struct Frame diff --git a/Src/cobs.c b/Src/cobs.c index be1c2930..36f4ae17 100644 --- a/Src/cobs.c +++ b/Src/cobs.c @@ -132,6 +132,14 @@ void COBSPump( struct COBS *t, const uint8_t *incoming, int len, break; + case COBS_DRAINING: // --------------------------------------------------------------- + if ( COBS_SYNC_CHAR == *fp ) + { + t->s = COBS_IDLE; + } + + break; + case COBS_RXING: // ------------------------------------------------------------------- t->intervalCount--; @@ -160,7 +168,7 @@ void COBSPump( struct COBS *t, const uint8_t *incoming, int len, if ( ( t->f.len > COBS_MAX_PACKET_LEN ) || ( COBS_SYNC_CHAR == *fp ) ) { t->error++; - t->s = COBS_IDLE; + t->s = COBS_DRAINING; } else { From 21285f8346257d03eb7e3450e9c74bd55da4913a Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Sat, 21 Sep 2024 12:35:55 +0100 Subject: [PATCH 04/46] Documentation updates for 2.2.0 --- CHANGES.md | 4 +++- README.md | 44 ++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 45 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5b0cd5d7..59fc8c66 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,5 +1,7 @@ -In Progress (Version 2.2.0) +21st Sept 2024 (Version 2.2.0) +* Add COBS draining state to re-sync as quickly as possible +* Report when client is disconnected for not keeping up * Addition of orbflow support (COBS over arbitary bearer with protocol on top) * Support for ORBTrace 1.4 series gateware * Support in-probe TPIU frame stripping diff --git a/README.md b/README.md index 1c0ef8b3..0a249769 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ ![Screenshot](https://raw.githubusercontent.com/orbcode/orbuculum/main/Docs/title.png) -This is the branch for the development of Orbuculum V2.2.0 which is currently in feature freeze and Beta test. Bugfixes for 2.2.0 will be done in this branch. Development is generally done in feature branches and folded into main as those features mature - that will be post 2.2.0. +This is Orbuculum V2.2.0. Bugfixes for 2.2.x will be done in this branch. Development is generally done in feature branches and folded into main as those features mature - those are post 2.2.0. Version 2.2.0 builds on 2.1.0 and adds several new CPU families, improved client application handling and the start of ETM4 support. Stats and timing are also much improved and the whole communications subsystem has been simplified and streamlined. Most importantly though, we have moved from 'legacy' protocol (basically, the exact same protocol that flows from the chip) for communications to 'orbflow' protocol. Orbflow protocol is an extensible packet oriented protocol which provides a more compact representation of the probe data. By default orbflow is used transparently between orbuculum and client applications. If you have an ORBTrace 1.4.0 or higher version then it is also used for communication from the probe to orbuculum. If you have your own legacy applications, or a version of ORBTrace less that 1.4.0, then the system will fall back to legacy protocol transparently. You can have a hybrid arrangement where some clients use legacy protocol and some use orbflow no problem. As you might imagine this can quickly become complex so please yell up if any edge cases don't seem to work correctly! @@ -98,7 +98,7 @@ from the target; * SEGGER JLink * generic USB TTL Serial Interfaces * FTDI High speed serial interfaces -* OpenOCD (Add a line like `tpiu config internal :3443 uart off 32000000` to your openocd config to use it.) +* OpenOCD (Add a line like `tpiu config internal :3443 uart off 32000000` to your openocd config to use it...more detailed configuration info at the bottom of this document) * PyOCD (Add options like `enable_swv: True`, `swv_system_clock: 32000000` to your `pyocd.yml` to use it.) * ECPIX-5 ECP5 Breakout Board for parallel trace * Anything capable of saving the raw SWO data to a file @@ -1132,3 +1132,43 @@ In order to ease pain of this issue, Orbuculum distribution for Windows built on The later approach (file replacement) works fine for PyOCD (replace `libusb-1.0.dll` file in `/Lib/site-packages/libusb_package`) and fails to work with xPack OpenOCD (due to the way `libftdi.dll` is built). Please report both success (this will increase chances of merging patch to upstream libusb) and failures (so we will be able to identify and fix issues introduced by patch) with this approach. + +Notes on using orbuculum with openocd +===================================== + +Taylorh140 made some good notes about getting openocd working with orbuculum on a STM32F429 target. +They are repeated here; + +Openocd has a directory of scripts it uses for connecting. These are typically located in the +`..../share/scripts` folder so if you're connecting to a particular board or chip using one of +these you need to add a line to it to it. A typical file with line to open a tcp server listening to port 3443 +and let the SWV know that the cpu clock rate is 168Mhz would be; + +``` +source [find interface/stlink.cfg] +transport select hla_swd +set WORKAREASIZE 0x20000 +source [find target/stm32f4x.cfg] +reset_config srst_only + +tpiu config internal :3443 uart off 168000000 +``` + +You can then start openocd with a command like `openocd -f `. You might see a line +like `Info : DEPRECIATED 'tpiu config'` but that should be ok. You should now be able to connect +orb clients directly to openocd, something like; + +``` +> orbcat -s localhost:3443 -c0,"%c" +ABCDEFGHIJKLMNOPQRSTUVWXYZ +ABCDEFGHIJKLMNOPQRSTUVWXYZ +ABCDEFGHIJKL...etc +``` + +Things to try if this doesn't work; + +* make sure your device is connected +* make sure its powered on +* make sure there is no typo's in the .cfg file. +* make sure your application is running ('c' in gdb) +* get help from the openocd or orbuculum discord servers From 2f3570edd14a5586fa902fcce30a63db2165a7e9 Mon Sep 17 00:00:00 2001 From: Jarno Malmari Date: Sat, 19 Oct 2024 20:47:57 +0300 Subject: [PATCH 05/46] Fix C++ function names cut too early --- Src/symbols.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Src/symbols.c b/Src/symbols.c index 2158ef16..16251145 100644 --- a/Src/symbols.c +++ b/Src/symbols.c @@ -261,6 +261,11 @@ static enum LineType _getLineType( char *sourceLine, char *p1, char *p2, char *p /* If it has something with in it, it's a proc label (function) */ if ( 2 == sscanf( sourceLine, "%[0-9a-fA-F] <%[^>]>", p1, p2 ) ) { + /* Demangled C++ names may have multiple ">" characters. Expand until last one. */ + const char *const beg = strchr(sourceLine, '<') + 1; + const char *const end = strrchr(beg, '>'); + (void)memcpy(p2, beg, end - beg); + p2[end - beg] = '\0'; return LT_PROC_LABEL; } From a53c22e31fc272d5cc0ef20ac8bc63ef0e9ac6d7 Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 24 Oct 2024 10:48:06 +0200 Subject: [PATCH 06/46] traceDecoder_etm4 bug fixes --- Src/traceDecoder_etm4.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/Src/traceDecoder_etm4.c b/Src/traceDecoder_etm4.c index d90c7f8a..90caa9ac 100644 --- a/Src/traceDecoder_etm4.c +++ b/Src/traceDecoder_etm4.c @@ -185,6 +185,11 @@ static bool _pumpAction( struct TRACEDecoderEngine *e, struct TRACECPUState *cpu } else { + if( c == 0x05 && j->asyncCount == 1) + { + cpu->overflows++; + DEBUG( "Overflow Detected. ReSync Trace Stream:" EOL ); + } j->asyncCount = c ? 0 : j->asyncCount + 1; switch ( j->p ) @@ -336,7 +341,7 @@ static bool _pumpAction( struct TRACEDecoderEngine *e, struct TRACECPUState *cpu case 0b11000000 ... 0b11010100: case 0b11100000 ... 0b11110100: /* Atom format 6, Figure 6-44, Pg 6.307 */ - cpu->eatoms = ( c & 0x1f ) + 3; + cpu->eatoms = ( c & 0x1f ) + 4; cpu->instCount = cpu->eatoms; cpu->disposition = ( 1 << ( cpu->eatoms ) ) - 1; @@ -404,6 +409,8 @@ static bool _pumpAction( struct TRACEDecoderEngine *e, struct TRACECPUState *cpu cpu->addr = j->q[match].addr; retVal = TRACE_EV_MSG_RXED; _stateChange( cpu, EV_CH_ADDRESS ); + _stackQ( j ); + j->q[0].addr = cpu->addr; break; case 0b10010101: /* Short address, IS0 short, Figure 6-32, Pg 6-294 */ @@ -685,7 +692,7 @@ static bool _pumpAction( struct TRACEDecoderEngine *e, struct TRACECPUState *cpu } else { - if ( j->idx == 8 ) + if ( j->idx == 9 ) { /* Second byte of IS1 case - mask MSB */ j->q[0].addr = ( j->q[0].addr & ( ~( 0x7F << j->idx ) ) ) | ( ( c & 0x7f ) << ( j->idx ) ); From 3c326d2d3759fc20c9784493021f2fe2776bb6a9 Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 24 Oct 2024 11:04:05 +0200 Subject: [PATCH 07/46] TraceDecoder add overflow debug parameter --- Inc/traceDecoder.h | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Inc/traceDecoder.h b/Inc/traceDecoder.h index a134f191..1940d945 100644 --- a/Inc/traceDecoder.h +++ b/Inc/traceDecoder.h @@ -143,6 +143,9 @@ struct TRACECPUState // Convinience, for debug reporting genericsReportCB report; + + // Debugging + uint64_t overflows; }; // ============================================================================ From 29c8a18e60c46cfc3be15c47a2579e86e82e0dff Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 24 Oct 2024 11:12:19 +0200 Subject: [PATCH 08/46] loadelf fix could not find inline functions, LDR was missing --- Src/loadelf.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/Src/loadelf.c b/Src/loadelf.c index ea3295a1..511c14d0 100644 --- a/Src/loadelf.c +++ b/Src/loadelf.c @@ -369,15 +369,16 @@ static void _processFunctionDie( struct symbol *p, Dwarf_Debug dbg, Dwarf_Die di attr_tag = DW_AT_abstract_origin; dwarf_attr( die, attr_tag, &attr_data, 0 ); dwarf_global_formref( attr_data, &abstract_origin_offset, 0 ); - dwarf_offdie_b( dbg, abstract_origin_offset, IS_INFO, &abstract_origin_die, 0 ); - isinline = true; - } - else - { - dwarf_highpc_b ( die, &h, 0, &formclass, 0 ); - dwarf_lowpc ( die, &l, 0 ); + if (DW_DLV_OK == dwarf_offdie_b( dbg, abstract_origin_offset, IS_INFO, &abstract_origin_die, 0 )) + { + isinline = true; + name_die = abstract_origin_die; + } } + dwarf_highpc_b ( die, &h, 0, &formclass, 0 ); + dwarf_lowpc ( die, &l, 0 ); + if ( formclass == DW_FORM_CLASS_CONSTANT ) { h += l; @@ -1001,7 +1002,7 @@ char *symbolDisassembleLine( struct symbol *p, enum instructionClass *ic, symbol if ( !p->caphandle ) { /* Disassembler isn't initialised yet */ - if ( cs_open( CS_ARCH_ARM, CS_MODE_THUMB + CS_MODE_LITTLE_ENDIAN, &p->caphandle ) != CS_ERR_OK ) + if ( cs_open( CS_ARCH_ARM, CS_MODE_THUMB + CS_MODE_LITTLE_ENDIAN + CS_MODE_MCLASS, &p->caphandle ) != CS_ERR_OK ) { return NULL; } @@ -1044,6 +1045,14 @@ char *symbolDisassembleLine( struct symbol *p, enum instructionClass *ic, symbol && strstr( insn->op_str, "pc" ) ) ) ? LE_IC_JUMP : 0; + // create a copy to check for pc + char *copy = strdup(insn->op_str); + *ic |= ( + ( ( ( insn->id == ARM_INS_LDR ) ) + && strstr(strtok(copy,","), "pc" ) ) + ) ? LE_IC_JUMP : 0; + // free the copy + free(copy); /* Was it an exception return? */ *ic |= ( ( insn->id == ARM_INS_ERET ) ) ? LE_IC_JUMP | LE_IC_IRET : 0; @@ -1072,7 +1081,7 @@ char *symbolDisassembleLine( struct symbol *p, enum instructionClass *ic, symbol if ( newaddr ) { - *newaddr = detail->arm.operands[0].imm; + *newaddr = detail->arm.operands[n].imm; } break; From f0abfb86c0f0001604786fcf2e13bd6da0e476ac Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 24 Oct 2024 11:14:29 +0200 Subject: [PATCH 09/46] update --- Src/loadelf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Src/loadelf.c b/Src/loadelf.c index 511c14d0..1c2749fa 100644 --- a/Src/loadelf.c +++ b/Src/loadelf.c @@ -1045,14 +1045,14 @@ char *symbolDisassembleLine( struct symbol *p, enum instructionClass *ic, symbol && strstr( insn->op_str, "pc" ) ) ) ? LE_IC_JUMP : 0; - // create a copy to check for pc + /* create a copy to check if load in pc */ char *copy = strdup(insn->op_str); *ic |= ( ( ( ( insn->id == ARM_INS_LDR ) ) && strstr(strtok(copy,","), "pc" ) ) ) ? LE_IC_JUMP : 0; - // free the copy free(copy); + /* Was it an exception return? */ *ic |= ( ( insn->id == ARM_INS_ERET ) ) ? LE_IC_JUMP | LE_IC_IRET : 0; From 5f04cb4df5c5d38636802e2817c2f19766ae93b1 Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 24 Oct 2024 11:14:36 +0200 Subject: [PATCH 10/46] loadelf fix could not find inline functions, LDR was missing --- Src/loadelf.c | 27 ++++++++++++++++++--------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/Src/loadelf.c b/Src/loadelf.c index ea3295a1..1c2749fa 100644 --- a/Src/loadelf.c +++ b/Src/loadelf.c @@ -369,15 +369,16 @@ static void _processFunctionDie( struct symbol *p, Dwarf_Debug dbg, Dwarf_Die di attr_tag = DW_AT_abstract_origin; dwarf_attr( die, attr_tag, &attr_data, 0 ); dwarf_global_formref( attr_data, &abstract_origin_offset, 0 ); - dwarf_offdie_b( dbg, abstract_origin_offset, IS_INFO, &abstract_origin_die, 0 ); - isinline = true; - } - else - { - dwarf_highpc_b ( die, &h, 0, &formclass, 0 ); - dwarf_lowpc ( die, &l, 0 ); + if (DW_DLV_OK == dwarf_offdie_b( dbg, abstract_origin_offset, IS_INFO, &abstract_origin_die, 0 )) + { + isinline = true; + name_die = abstract_origin_die; + } } + dwarf_highpc_b ( die, &h, 0, &formclass, 0 ); + dwarf_lowpc ( die, &l, 0 ); + if ( formclass == DW_FORM_CLASS_CONSTANT ) { h += l; @@ -1001,7 +1002,7 @@ char *symbolDisassembleLine( struct symbol *p, enum instructionClass *ic, symbol if ( !p->caphandle ) { /* Disassembler isn't initialised yet */ - if ( cs_open( CS_ARCH_ARM, CS_MODE_THUMB + CS_MODE_LITTLE_ENDIAN, &p->caphandle ) != CS_ERR_OK ) + if ( cs_open( CS_ARCH_ARM, CS_MODE_THUMB + CS_MODE_LITTLE_ENDIAN + CS_MODE_MCLASS, &p->caphandle ) != CS_ERR_OK ) { return NULL; } @@ -1044,6 +1045,14 @@ char *symbolDisassembleLine( struct symbol *p, enum instructionClass *ic, symbol && strstr( insn->op_str, "pc" ) ) ) ? LE_IC_JUMP : 0; + /* create a copy to check if load in pc */ + char *copy = strdup(insn->op_str); + *ic |= ( + ( ( ( insn->id == ARM_INS_LDR ) ) + && strstr(strtok(copy,","), "pc" ) ) + ) ? LE_IC_JUMP : 0; + free(copy); + /* Was it an exception return? */ *ic |= ( ( insn->id == ARM_INS_ERET ) ) ? LE_IC_JUMP | LE_IC_IRET : 0; @@ -1072,7 +1081,7 @@ char *symbolDisassembleLine( struct symbol *p, enum instructionClass *ic, symbol if ( newaddr ) { - *newaddr = detail->arm.operands[0].imm; + *newaddr = detail->arm.operands[n].imm; } break; From ff18fc296e71a853bee455abc839b1c42a8be5c1 Mon Sep 17 00:00:00 2001 From: Lukas Date: Thu, 24 Oct 2024 16:45:33 +0200 Subject: [PATCH 11/46] _processFunctionDie fix --- Src/loadelf.c | 1 - 1 file changed, 1 deletion(-) diff --git a/Src/loadelf.c b/Src/loadelf.c index 1c2749fa..fc9e7c15 100644 --- a/Src/loadelf.c +++ b/Src/loadelf.c @@ -372,7 +372,6 @@ static void _processFunctionDie( struct symbol *p, Dwarf_Debug dbg, Dwarf_Die di if (DW_DLV_OK == dwarf_offdie_b( dbg, abstract_origin_offset, IS_INFO, &abstract_origin_die, 0 )) { isinline = true; - name_die = abstract_origin_die; } } From 3dfda27d3cb6b6e63ce92ceaa840a51e641cb00d Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Sun, 27 Oct 2024 23:10:10 +0000 Subject: [PATCH 12/46] Fix legacy port reflection when monitoring is not switched on --- Src/orbuculum.c | 7 ++----- Src/symbols.c | 6 +++--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/Src/orbuculum.c b/Src/orbuculum.c index 8dd7ded4..93caaf4a 100644 --- a/Src/orbuculum.c +++ b/Src/orbuculum.c @@ -1009,11 +1009,8 @@ static void _handleBlock( struct RunTime *r, ssize_t fillLevel, uint8_t *buffer if ( r->usingOFLOW ) { - if ( r->options->intervalReportTime ) - { - /* We need to decode this so we can get the stats out of it .. we don't bother if we don't need stats */ - OFLOWPump( &r->oflow, buffer, fillLevel, _OFLOWpacketRxed, r ); - } + /* We need to decode this so we can get the stats out of it, and to reflect it out */ + OFLOWPump( &r->oflow, buffer, fillLevel, _OFLOWpacketRxed, r ); /* ...and reflect this packet to the outgoing OFLOW channels, if we don't need to reconstruct them */ if ( !r->options->useTPIU ) diff --git a/Src/symbols.c b/Src/symbols.c index 16251145..c9baf22b 100644 --- a/Src/symbols.c +++ b/Src/symbols.c @@ -262,9 +262,9 @@ static enum LineType _getLineType( char *sourceLine, char *p1, char *p2, char *p if ( 2 == sscanf( sourceLine, "%[0-9a-fA-F] <%[^>]>", p1, p2 ) ) { /* Demangled C++ names may have multiple ">" characters. Expand until last one. */ - const char *const beg = strchr(sourceLine, '<') + 1; - const char *const end = strrchr(beg, '>'); - (void)memcpy(p2, beg, end - beg); + const char *const beg = strchr( sourceLine, '<' ) + 1; + const char *const end = strrchr( beg, '>' ); + ( void )memcpy( p2, beg, end - beg ); p2[end - beg] = '\0'; return LT_PROC_LABEL; } From 7eff03927dcd3add3f7e1b08fb238589b05226d0 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Sun, 27 Oct 2024 23:18:17 +0000 Subject: [PATCH 13/46] Fix redundant access to DBGMCU for SAMD5 per issue #157 --- Support/gdbtrace.init | 9 --------- 1 file changed, 9 deletions(-) diff --git a/Support/gdbtrace.init b/Support/gdbtrace.init index 00d5b728..b4aacac1 100644 --- a/Support/gdbtrace.init +++ b/Support/gdbtrace.init @@ -1550,15 +1550,6 @@ define enableSAMD5XTRACE set *(unsigned char *)(0x41008000+0x80*2+0x40+24) = (($drive) << 6) | 1 end - # Set number of bits in DBGMCU_CR - set *0xE0042004 &= ~(3<<6) - - if ($bits<3) - set *0xE0042004 |= ((($bits+1)<<6) | (1<<5)) - else - set *0xE0042004 |= ((3<<6) | (1<<5)) - end - # Enable Trace TRCENA (DCB DEMCR) set *($CDBBASE+0xC)=(1<<24) From 62b3a29d8f8e99b25ee990361793538baafdcb3b Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Sun, 27 Oct 2024 23:28:10 +0000 Subject: [PATCH 14/46] remove reference to TPIU and ETM LAR's per #156 --- Support/gdbtrace.init | 2 -- 1 file changed, 2 deletions(-) diff --git a/Support/gdbtrace.init b/Support/gdbtrace.init index b4aacac1..00fa80c9 100644 --- a/Support/gdbtrace.init +++ b/Support/gdbtrace.init @@ -994,8 +994,6 @@ define _doTRACE # Must be called with $bits containing number of bits to set trace for set *($ITMBASE+0xfb0) = 0xc5acce55 - set *($ETMBASE+0xfb0) = 0xc5acce55 - set *($TPIUBASE+0xfb0) = 0xc5acce55 # Set port size (TPIU_CSPSR) set *($TPIUBASE+4) = (1<<$bits) From 83463c0ecddf66a8ce6d847e1d193dac3f015cc7 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Fri, 29 Nov 2024 08:10:02 +0000 Subject: [PATCH 15/46] Avoid memory leak --- Src/orbtop.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/Src/orbtop.c b/Src/orbtop.c index f8cf205b..9502065d 100644 --- a/Src/orbtop.c +++ b/Src/orbtop.c @@ -422,13 +422,19 @@ uint32_t _consolodateReport( struct reportLine **returnReport, uint32_t *returnR } else { + a = ( struct visitedAddr * )calloc( 1, sizeof( struct visitedAddr ) ); + MEMCHECKV( a ); + a->visits = _r.sleeps; + n = ( struct nameEntry * )malloc( sizeof( struct nameEntry ) ); - } + n->fileindex = NO_FILE; + n->functionindex = FN_SLEEPING; + n->addr = FN_SLEEPING; + n->line = 0; - n->fileindex = NO_FILE; - n->functionindex = FN_SLEEPING; - n->addr = 0; - n->line = 0; + a->n = n; + HASH_ADD_INT( _r.addresses, n->addr, a ); + } report[reportLines].n = n; report[reportLines].count = _r.sleeps; @@ -808,16 +814,18 @@ void _handlePCSample( struct pcSampleMsg *m, struct ITMDecoder *i ) void _flushHash( void ) { - struct visitedAddr *a; - UT_hash_handle hh; + struct visitedAddr *a, *tmp; - for ( a = _r.addresses; a != NULL; a = hh.next ) + HASH_ITER( hh, _r.addresses, a, tmp ) { - hh = a->hh; + if ( a->n ) + { + free( a->n ); + } + + HASH_DEL( _r.addresses, a ); free( a ); } - - _r.addresses = NULL; } // ==================================================================================================== // Pump characters into the itm decoder From 0e341371ef7568246e7bf124b6d4e0f5400f3267 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Fri, 29 Nov 2024 12:17:34 +0000 Subject: [PATCH 16/46] Prettyprint fixups --- Inc/traceDecoder.h | 2 +- Src/loadelf.c | 13 +++++++------ Src/traceDecoder_etm4.c | 3 ++- 3 files changed, 10 insertions(+), 8 deletions(-) diff --git a/Inc/traceDecoder.h b/Inc/traceDecoder.h index 1940d945..9063540d 100644 --- a/Inc/traceDecoder.h +++ b/Inc/traceDecoder.h @@ -145,7 +145,7 @@ struct TRACECPUState genericsReportCB report; // Debugging - uint64_t overflows; + uint64_t overflows; }; // ============================================================================ diff --git a/Src/loadelf.c b/Src/loadelf.c index fc9e7c15..e10652c0 100644 --- a/Src/loadelf.c +++ b/Src/loadelf.c @@ -369,7 +369,8 @@ static void _processFunctionDie( struct symbol *p, Dwarf_Debug dbg, Dwarf_Die di attr_tag = DW_AT_abstract_origin; dwarf_attr( die, attr_tag, &attr_data, 0 ); dwarf_global_formref( attr_data, &abstract_origin_offset, 0 ); - if (DW_DLV_OK == dwarf_offdie_b( dbg, abstract_origin_offset, IS_INFO, &abstract_origin_die, 0 )) + + if ( DW_DLV_OK == dwarf_offdie_b( dbg, abstract_origin_offset, IS_INFO, &abstract_origin_die, 0 ) ) { isinline = true; } @@ -1045,13 +1046,13 @@ char *symbolDisassembleLine( struct symbol *p, enum instructionClass *ic, symbol ) ? LE_IC_JUMP : 0; /* create a copy to check if load in pc */ - char *copy = strdup(insn->op_str); + char *copy = strdup( insn->op_str ); *ic |= ( ( ( ( insn->id == ARM_INS_LDR ) ) - && strstr(strtok(copy,","), "pc" ) ) + && strstr( strtok( copy, "," ), "pc" ) ) ) ? LE_IC_JUMP : 0; - free(copy); - + free( copy ); + /* Was it an exception return? */ *ic |= ( ( insn->id == ARM_INS_ERET ) ) ? LE_IC_JUMP | LE_IC_IRET : 0; @@ -1080,7 +1081,7 @@ char *symbolDisassembleLine( struct symbol *p, enum instructionClass *ic, symbol if ( newaddr ) { - *newaddr = detail->arm.operands[n].imm; + *newaddr = detail->arm.operands[n].imm; } break; diff --git a/Src/traceDecoder_etm4.c b/Src/traceDecoder_etm4.c index 90caa9ac..99811f81 100644 --- a/Src/traceDecoder_etm4.c +++ b/Src/traceDecoder_etm4.c @@ -185,11 +185,12 @@ static bool _pumpAction( struct TRACEDecoderEngine *e, struct TRACECPUState *cpu } else { - if( c == 0x05 && j->asyncCount == 1) + if ( c == 0x05 && j->asyncCount == 1 ) { cpu->overflows++; DEBUG( "Overflow Detected. ReSync Trace Stream:" EOL ); } + j->asyncCount = c ? 0 : j->asyncCount + 1; switch ( j->p ) From 1df69573841db1fa30ed721b4ca0310034cbc773 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Wed, 11 Dec 2024 07:51:04 +0000 Subject: [PATCH 17/46] Add diagnostics about size of target elf --- Src/orbtop.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/Src/orbtop.c b/Src/orbtop.c index 9502065d..0be99d74 100644 --- a/Src/orbtop.c +++ b/Src/orbtop.c @@ -1283,6 +1283,12 @@ int main( int argc, char *argv[] ) genericsReport( V_WARN, "Loaded %s" EOL, options.elffile ); + if ( _r.s ) + { + genericsReport( V_INFO, "Files: %d" EOL "Functions: %d" EOL "Source: %d" EOL, _r.s->fileCount, _r.s->functionCount, _r.s->sourceCount ); + } + + /* Reset the handlers before we start */ ITMDecoderInit( &_r.i, options.forceITMSync ); OFLOWInit( &_r.c ); @@ -1407,6 +1413,11 @@ int main( int argc, char *argv[] ) } genericsReport( V_WARN, "Loaded %s" EOL, options.elffile ); + + if ( _r.s ) + { + genericsReport( V_INFO, "Files: %d" EOL "Functions: %d" EOL "Source: %d" EOL, _r.s->fileCount, _r.s->functionCount, _r.s->sourceCount ); + } } From 5111550e269d8f5a1f3c758722a0864bb26d41d9 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Wed, 18 Dec 2024 17:50:39 +0000 Subject: [PATCH 18/46] Explicitly print any address that doesn't match --- Src/symbols.c | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/Src/symbols.c b/Src/symbols.c index c9baf22b..d428b79c 100644 --- a/Src/symbols.c +++ b/Src/symbols.c @@ -30,7 +30,7 @@ #define NO_FILE_TXT "No Source" //#define GPTI_DEBUG 1 /* Define this for objdump data collection state machine trace */ - +//#define _DUMP_SYMBOLS /* Define this to dump all symbols at start of run */ #ifdef GPTI_DEBUG #define GTPIP(...) { fprintf(stderr, __VA_ARGS__); } #else @@ -854,6 +854,26 @@ static enum symbolErr _getTargetProgramInfo( struct SymbolSet *s ) #endif _sortLines( s ); + +#ifdef _DUMP_SYMBOLS + uint32_t sline = 0; + uint32_t functionindex = s->sources[0].functionIdx; + uint32_t firstaddr = s->sources[0].startAddr; + + while ( sline < s->sourceCount - 1 ) + { + if ( s->sources[sline + 1].functionIdx != functionindex ) + { + printf( "%08x-%08x %s" EOL, firstaddr, s->sources[sline].endAddr, s->functions[functionindex].name ); + functionindex = s->sources[sline + 1].functionIdx; + firstaddr = s->sources[sline + 1].startAddr; + } + + sline++; + } + +#endif + return SYMBOL_OK; } // ==================================================================================================== @@ -931,6 +951,7 @@ bool SymbolLookup( struct SymbolSet *s, uint32_t addr, struct nameEntry *n ) } + printf("%08x ",addr); n->fileindex = n->functionindex = n->line = 0; n->source = ""; n->assy = NULL; From 4a13f878fbe33ec9f13ac4de034f2a83d146bc08 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Fri, 20 Dec 2024 22:26:58 +0000 Subject: [PATCH 19/46] Add comms pacing to orbtop --- Src/itmDecoder.c | 4 +++- Src/orbtop.c | 32 ++++++++++++++++++++++++++++++-- 2 files changed, 33 insertions(+), 3 deletions(-) diff --git a/Src/itmDecoder.c b/Src/itmDecoder.c index 2543a647..853c8730 100644 --- a/Src/itmDecoder.c +++ b/Src/itmDecoder.c @@ -14,6 +14,9 @@ #include "itmDecoder.h" #include "msgDecoder.h" +// Define this to get transitions printed out +#define DEBUG + #ifdef DEBUG #include #include "generics.h" @@ -28,7 +31,6 @@ #define MAX_PACKET (5) #define DEFAULT_PAGE_REGISTER (0x07) -// Define this to get transitions printed out // ==================================================================================================== struct ITMDecoder *ITMDecoderCreate( void ) diff --git a/Src/orbtop.c b/Src/orbtop.c index 0be99d74..3f1b0b52 100644 --- a/Src/orbtop.c +++ b/Src/orbtop.c @@ -92,6 +92,7 @@ struct /* Record for options, either defau char *outfile; /* File to output current information */ char *logfile; /* File to output historic information */ bool mono; /* Supress colour in output */ + int paceDelay; /* Delay between blocks of data transmission in file readout */ uint32_t cutscreen; /* Cut screen output after specified number of lines */ uint32_t maxRoutines; /* Historic information to emit */ bool lineDisaggregation; /* Aggregate per line or per function? */ @@ -906,6 +907,7 @@ void _printHelp( const char *const progName ) 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 ); @@ -941,6 +943,7 @@ static struct option _longOptions[] = {"output-file", required_argument, NULL, 'o'}, {"objdump-opts", required_argument, NULL, 'O'}, {"protocol", required_argument, NULL, 'p'}, + {"pace", required_argument, NULL, 'P'}, {"routines", required_argument, NULL, 'r'}, {"report-files", no_argument, NULL, 'R'}, {"server", required_argument, NULL, 's'}, @@ -957,7 +960,7 @@ bool _processOptions( int argc, char *argv[] ) bool protExplicit = false; bool serverExplicit = false; - while ( ( c = getopt_long ( argc, argv, "c:d:DEe:f:g:hVI:j:lMnO:o:p:r:Rs:t:v:", _longOptions, &optionIndex ) ) != -1 ) + while ( ( c = getopt_long ( argc, argv, "c:d:DEe:f:g:hVI:j:lMnO:o:p:P:r:Rs:t:v:", _longOptions, &optionIndex ) ) != -1 ) switch ( c ) { // ------------------------------------ @@ -1057,6 +1060,19 @@ bool _processOptions( int argc, char *argv[] ) // ------------------------------------ + case 'P': + options.paceDelay = atoi( optarg ); + + if ( options.paceDelay <= 0 ) + { + genericsReport( V_ERROR, "paceDelay is out of range" EOL ); + return false; + } + + break; + + // ------------------------------------ + case 'O': options.odoptions = optarg; break; @@ -1154,6 +1170,7 @@ bool _processOptions( int argc, char *argv[] ) if ( options.file ) { + genericsReport( V_INFO, "Pace Delay : %dus" EOL, options.paceDelay ); genericsReport( V_INFO, "Input File : %s", options.file ); } else @@ -1181,7 +1198,13 @@ bool _processOptions( int argc, char *argv[] ) default: genericsReport( V_INFO, "Decoding unknown" EOL ); - break; + return false; + } + + if ( ( options.paceDelay ) && ( !options.file ) ) + { + genericsReport( V_ERROR, "Pace Delay only makes sense when input is from a file" EOL ); + return false; } return OK; @@ -1490,6 +1513,11 @@ int main( int argc, char *argv[] ) ITMDecoderGetStats( &_r.i )->tpiuSyncCount = 0; } } + + if ( options.paceDelay ) + { + usleep( options.paceDelay ); + } } stream->close( stream ); From 9b002423c662fc8d82f8103d701e0210b830224a Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Sat, 21 Dec 2024 22:45:21 +0000 Subject: [PATCH 20/46] Make protocol spec mandatory in orbtop when source is set --- .github/workflows/build-osx.yml | 3 ++- Inc/generics.h | 1 + README.md | 7 ++++++- Src/orbtop.c | 25 +++++++++++++------------ Src/symbols.c | 2 -- 5 files changed, 22 insertions(+), 16 deletions(-) diff --git a/.github/workflows/build-osx.yml b/.github/workflows/build-osx.yml index 68797735..cc3ade32 100644 --- a/.github/workflows/build-osx.yml +++ b/.github/workflows/build-osx.yml @@ -6,8 +6,9 @@ on: jobs: osx: - runs-on: macos-12 + runs-on: macos-14 steps: + - run: python3 -m pip config set global.break-system-packages true - run: brew install zmq sdl2 libelf - run: pip3 install meson - run: pip3 install ninja diff --git a/Inc/generics.h b/Inc/generics.h index 7f1d8b23..becbea74 100644 --- a/Inc/generics.h +++ b/Inc/generics.h @@ -20,6 +20,7 @@ extern "C" { #endif /* Error return codes .. may already be defined by ncurses */ +typedef int errcode; #ifndef OK #define OK 0 #endif diff --git a/README.md b/README.md index 0a249769..d22a58e2 100644 --- a/README.md +++ b/README.md @@ -737,7 +737,8 @@ line for orbtop would be; One useful command line option for orbtop (and indeed, for the majority of the rest of the suite) is `-s localhost:2332`, which will connect directly to any source you might have exporting -SWO data on its TCP its port, with no requirement for the orbuculum multiplexer in the way. +SWO data on its TCP its port, with no requirement for the orbuculum multiplexer in the way. If +you set the source explicitly, you also need to set the protocol explicitly using `-p`. Command line options for orbtop are; @@ -769,6 +770,10 @@ Command line options for orbtop are; `-O, --objdump-opts [opts]`: Set options to pass directly to objdump + `-p, --protocol [OFLOW|ITM]`: Protocol to communicate. Must be set explicitly if -s is set + + `-P, --pace `: Delay in block of data transmission to clients + `-r, --routines `: Number of lines to record in history file `-R, --report-file [filename]`: Report filenames as part of function discriminator diff --git a/Src/orbtop.c b/Src/orbtop.c index 3f1b0b52..8674aac1 100644 --- a/Src/orbtop.c +++ b/Src/orbtop.c @@ -953,7 +953,7 @@ static struct option _longOptions[] = {NULL, no_argument, NULL, 0} }; // ==================================================================================================== -bool _processOptions( int argc, char *argv[] ) +errcode _processOptions( int argc, char *argv[] ) { int c, optionIndex = 0; @@ -1053,7 +1053,7 @@ bool _processOptions( int argc, char *argv[] ) if ( options.protocol == PROT_UNKNOWN ) { genericsReport( V_ERROR, "Unrecognised protocol type" EOL ); - return false; + return ERR; } break; @@ -1066,7 +1066,7 @@ bool _processOptions( int argc, char *argv[] ) if ( options.paceDelay <= 0 ) { genericsReport( V_ERROR, "paceDelay is out of range" EOL ); - return false; + return ERR; } break; @@ -1082,7 +1082,7 @@ bool _processOptions( int argc, char *argv[] ) if ( !isdigit( *optarg ) ) { genericsReport( V_ERROR, "-v requires a numeric argument." EOL ); - return false; + return ERR; } genericsSetReportLevel( atoi( optarg ) ); @@ -1132,7 +1132,7 @@ bool _processOptions( int argc, char *argv[] ) // ------------------------------------ case 'V': _printVersion(); - return -EINVAL; + return ERR; // ------------------------------------ case '?': @@ -1145,25 +1145,26 @@ bool _processOptions( int argc, char *argv[] ) genericsReport( V_ERROR, "Unknown option character `\\x%x'." EOL, optopt ); } - return -EINVAL; + return ERR; // ------------------------------------ default: genericsReport( V_ERROR, "Unknown option %c" EOL, optopt ); - return -EINVAL; + return ERR; // ------------------------------------ } /* If we set an explicit server and port and didn't set a protocol chances are we want ITM, not OFLOW */ if ( serverExplicit && !protExplicit ) { - options.protocol = PROT_ITM; + genericsReport( V_ERROR, "Protocol must be explicit when server is explicit" EOL ); + return ERR; } if ( !options.elffile ) { genericsReport( V_ERROR, "Elf File not specified" EOL ); - exit( -EBADF ); + return ERR; } genericsReport( V_INFO, "orbtop version " GIT_DESCRIBE EOL ); @@ -1197,14 +1198,14 @@ bool _processOptions( int argc, char *argv[] ) break; default: - genericsReport( V_INFO, "Decoding unknown" EOL ); - return false; + genericsReport( V_ERROR, "Decoding unknown" EOL ); + return ERR; } if ( ( options.paceDelay ) && ( !options.file ) ) { genericsReport( V_ERROR, "Pace Delay only makes sense when input is from a file" EOL ); - return false; + return ERR; } return OK; diff --git a/Src/symbols.c b/Src/symbols.c index d428b79c..13bd93cb 100644 --- a/Src/symbols.c +++ b/Src/symbols.c @@ -950,8 +950,6 @@ bool SymbolLookup( struct SymbolSet *s, uint32_t addr, struct nameEntry *n ) return true; } - - printf("%08x ",addr); n->fileindex = n->functionindex = n->line = 0; n->source = ""; n->assy = NULL; From f142a7af5e6b523466725203c1773b174a64eae4 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Fri, 3 Jan 2025 09:24:21 +0000 Subject: [PATCH 21/46] Initial event counter reporting in orbtop. Untested --- Src/orbtop.c | 41 +++++++++++++++++++++++++++++++++++++---- 1 file changed, 37 insertions(+), 4 deletions(-) diff --git a/Src/orbtop.c b/Src/orbtop.c index 8674aac1..c25f05af 100644 --- a/Src/orbtop.c +++ b/Src/orbtop.c @@ -36,6 +36,9 @@ #define MSG_REORDER_BUFLEN (10) /* Maximum number of samples to re-order for timekeeping */ +#define DWT_NUM_EVENTS 6 +const char *evName[DWT_NUM_EVENTS] = {"CPI", "Exc", "Sleep", "LSU", "Fold", "Cyc"}; + struct visitedAddr /* Structure for Hashmap of visited/observed addresses */ { uint64_t visits; @@ -144,7 +147,8 @@ struct uint32_t SWPkt; /* Number of SW Packets received */ uint32_t TSPkt; /* Number of TS Packets received */ uint32_t HWPkt; /* Number of HW Packets received */ - + uint32_t dwt_event_acc[DWT_NUM_EVENTS]; /* Accumulator for DWT events */ + FILE *jsonfile; /* File where json output is being dumped */ uint32_t interrupts; uint32_t sleeps; @@ -344,10 +348,17 @@ void _handleException( struct excMsg *m, struct ITMDecoder *i ) }; } // ==================================================================================================== -void _handleDWTEvent( struct ITMDecoder *i, struct ITMPacket *p ) +// ==================================================================================================== +void _handleDWTEvent( struct dwtMsg *m, struct ITMPacket *p ) { - + for ( uint32_t i = 0; i < DWT_NUM_EVENTS; i++ ) + { + if ( m->event & ( 1 << i ) ) + { + _r.dwt_event_acc[i]++; + } + } } // ==================================================================================================== void _handleSW( struct ITMDecoder *i, struct ITMPacket *p ) @@ -449,6 +460,7 @@ uint32_t _consolodateReport( struct reportLine **returnReport, uint32_t *returnR *returnReport = report; *returnReportLines = reportLines; + return total; } // ==================================================================================================== @@ -712,6 +724,20 @@ static void _outputTop( uint32_t total, uint32_t reportLines, struct reportLine fclose( q ); } + bool havePrinted = false; + /* DWT Event counters */ + for ( uint32_t i = 0; i < DWT_NUM_EVENTS; i++ ) + { + if ( _r.dwt_event_acc[i] ) + { + havePrinted = true; + genericsPrintf( "%4s:%8d ",evName[i],_r.dwt_event_acc[i] ); + } + } + if ( havePrinted ) + { + genericsPrintf( EOL ); + } if ( options.outputExceptions ) { @@ -849,7 +875,7 @@ void _itmPumpProcess( uint8_t c ) /* MSG_DATA_ACCESS_WP */ NULL, /* MSG_DATA_RWWP */ NULL, /* MSG_PC_SAMPLE */ ( handlers )_handlePCSample, - /* MSG_DWT_EVENT */ NULL, + /* MSG_DWT_EVENT */ ( handlers )_handleDWTEvent, /* MSG_EXCEPTION */ ( handlers )_handleException, /* MSG_TS */ ( handlers )_handleTS }; @@ -1492,6 +1518,13 @@ int main( int argc, char *argv[] ) _r.er[e].visits = _r.er[e].maxDepth = _r.er[e].totalTime = _r.er[e].minTime = _r.er[e].maxTime = _r.er[e].maxWallTime = 0; } + /* ... and the event counters */ + for ( uint32_t i = 0; i < DWT_NUM_EVENTS; i++ ) + { + _r.dwt_event_acc[i]=0; + } + + /* It's safe to update these here because the ticks won't be updated until more * records arrive. */ if ( _r.ITMoverflows != ITMDecoderGetStats( &_r.i )->overflow ) From 1ec6487d7eeddac5c0e7945ce76eba57911d0e36 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Fri, 3 Jan 2025 16:50:05 +0000 Subject: [PATCH 22/46] Now with added testing --- Src/msgDecoder.c | 2 +- Src/orbtop.c | 36 +++++++++++++++++++----------------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Src/msgDecoder.c b/Src/msgDecoder.c index 1f982932..8245a3f3 100644 --- a/Src/msgDecoder.c +++ b/Src/msgDecoder.c @@ -36,7 +36,7 @@ static bool _handleDWTEvent( struct ITMPacket *packet, struct dwtMsg *decoded ) { decoded->msgtype = MSG_DWT_EVENT; - decoded->event = packet->d[1] & 0x2F; + decoded->event = packet->d[0] & 0x2F; return true; } // ==================================================================================================== diff --git a/Src/orbtop.c b/Src/orbtop.c index c25f05af..df883ec2 100644 --- a/Src/orbtop.c +++ b/Src/orbtop.c @@ -37,7 +37,7 @@ #define MSG_REORDER_BUFLEN (10) /* Maximum number of samples to re-order for timekeeping */ #define DWT_NUM_EVENTS 6 -const char *evName[DWT_NUM_EVENTS] = {"CPI", "Exc", "Sleep", "LSU", "Fold", "Cyc"}; +const char *evName[DWT_NUM_EVENTS] = {"CPI", "Exc", "Slp", "LSU", "Fld", "Cyc"}; struct visitedAddr /* Structure for Hashmap of visited/observed addresses */ { @@ -148,7 +148,7 @@ struct uint32_t TSPkt; /* Number of TS Packets received */ uint32_t HWPkt; /* Number of HW Packets received */ uint32_t dwt_event_acc[DWT_NUM_EVENTS]; /* Accumulator for DWT events */ - + FILE *jsonfile; /* File where json output is being dumped */ uint32_t interrupts; uint32_t sleeps; @@ -356,7 +356,7 @@ void _handleDWTEvent( struct dwtMsg *m, struct ITMPacket *p ) { if ( m->event & ( 1 << i ) ) { - _r.dwt_event_acc[i]++; + _r.dwt_event_acc[i]++; } } } @@ -725,19 +725,21 @@ static void _outputTop( uint32_t total, uint32_t reportLines, struct reportLine } bool havePrinted = false; + /* DWT Event counters */ for ( uint32_t i = 0; i < DWT_NUM_EVENTS; i++ ) { - if ( _r.dwt_event_acc[i] ) - { - havePrinted = true; - genericsPrintf( "%4s:%8d ",evName[i],_r.dwt_event_acc[i] ); + if ( _r.dwt_event_acc[i] ) + { + havePrinted = true; + genericsPrintf( "%4s:" C_DATA "%7d " C_RESET, evName[i], _r.dwt_event_acc[i] ); } } + if ( havePrinted ) - { - genericsPrintf( EOL ); - } + { + genericsPrintf( EOL ); + } if ( options.outputExceptions ) { @@ -1108,7 +1110,7 @@ errcode _processOptions( int argc, char *argv[] ) if ( !isdigit( *optarg ) ) { genericsReport( V_ERROR, "-v requires a numeric argument." EOL ); - return ERR; + return ERR; } genericsSetReportLevel( atoi( optarg ) ); @@ -1518,12 +1520,12 @@ int main( int argc, char *argv[] ) _r.er[e].visits = _r.er[e].maxDepth = _r.er[e].totalTime = _r.er[e].minTime = _r.er[e].maxTime = _r.er[e].maxWallTime = 0; } - /* ... and the event counters */ - for ( uint32_t i = 0; i < DWT_NUM_EVENTS; i++ ) - { - _r.dwt_event_acc[i]=0; - } - + /* ... and the event counters */ + for ( uint32_t i = 0; i < DWT_NUM_EVENTS; i++ ) + { + _r.dwt_event_acc[i] = 0; + } + /* It's safe to update these here because the ticks won't be updated until more * records arrive. */ From e3d78e67a4e787c7be1a74391e166109afd07ad8 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Wed, 12 Feb 2025 10:53:03 +0000 Subject: [PATCH 23/46] Add support for STM32 M33 devices (Specifically tested on STM32U5A5) --- CHANGES.md | 4 ++++ Support/gdbtrace.init | 53 ++++++++++++++++++++++++++++++++----------- 2 files changed, 44 insertions(+), 13 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 59fc8c66..d345fce9 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,3 +1,7 @@ +Version 2.3.0 In progress +* Add support for ITM rollover counters in orbtop (if they deliver information, they will be displayed) +* Add STM32 CORTEX-M33 support (Tested on STM32U5A5) + 21st Sept 2024 (Version 2.2.0) * Add COBS draining state to re-sync as quickly as possible diff --git a/Support/gdbtrace.init b/Support/gdbtrace.init index 00fa80c9..0eb38c26 100644 --- a/Support/gdbtrace.init +++ b/Support/gdbtrace.init @@ -9,7 +9,7 @@ GDB SWO Trace Configuration Helpers Setup Device ------------ STM32; - enableSTM32SWO : Enable SWO on STM32 pins (for F4 or F7 if 4/7 is passed as first argument) + enableSTM32SWO : Enable SWO on STM32 pins enableSTM32TRACE: Start TRACE on STM32 pins IMXRT; @@ -90,6 +90,7 @@ set $CPU_S32K344=6 set $CPU_IMXRT117X=7 set $CPU_KINETIS=8 set $CPU_SAMD5x=9 +set $CPU_STM32M33=10 # ==================================================================== set $CDBBASE=0xE000EDF0 @@ -97,11 +98,18 @@ set $DWTBASE=0xE0001000 set $ITMBASE=0xE0000000 set $TPIUBASE=0xE0040000 set $ETMBASE=0xE0041000 +set $CTIBASE=0xE0042000 define _setAddressesSTM32 # Locations in the memory map for interesting things on STM32 - set $RCCBASE = 0x40023800 - set $GPIOBASE = 0x40020000 + if ($CPU == $CPU_STM32M33) + set $RCCBASE = 0x46020c00 + set $GPIOBASE = 0x42020000 + set $DBGMCUBASE = 0xE0044000 + else + set $RCCBASE = 0x40023800 + set $GPIOBASE = 0x40020000 + set $DBGMCUBASE = 0xE0042000 end define _setAddressesIMXRT @@ -886,7 +894,11 @@ define enableSTM32SWO set $tgt = $arg0 end - set $CPU=$CPU_STM32 + if ($tgt==33) + set $CPU=$CPU_STM32M33 + else + set $CPU=$CPU_STM32 + end _setAddressesSTM32 if (($tgt==4) || ($tgt==7)) @@ -901,12 +913,13 @@ define enableSTM32SWO end # Common initialisation. # DBGMCU->CR |= DBGMCU_CR_TRACE_IOEN; - set *0xE0042004 |= 0x20 + set *($DBGMCUBASE+4) |= 0x20 #set language auto end document enableSTM32SWO -enableSTM32SWO Configure output pin on STM32 for SWO use. +enableSTM32SWO Configure output pin on STM32 for SWO use. + : Type of STM32 Device 4=f4, 7=f7, 33=M33 end # ==================================================================== define enableSAMD5XSWD @@ -1011,7 +1024,11 @@ define enableSTM32Pin set $_GPIOPORT = $GPIOBASE + 0x400 * $arg0 # Enable GPIO port in RCC - set *($RCCBASE + 0x30) |= (0x1<<$arg0) + if ($CPU == $CPU_STM32M33) + set *($RCCBASE + 0x8c) |= (0x1<<$arg0) + else + set *($RCCBASE + 0x30) |= (0x1<<$arg0) + end # MODER: Alternate Function set *($_GPIOPORT+0x00) &= ~(0x3<<2*$arg1) @@ -1055,6 +1072,7 @@ define enableSTM32TRACE set $bits=4 set $drive=1 + set $type=1 if $argc >= 1 set $bits = $arg0 @@ -1067,13 +1085,21 @@ define enableSTM32TRACE set $drive = $arg1 end + if $type >= 3 + set $drive = $arg2 + end + if ($drive > 3) help enableSTM32TRACE end set $bits = $bits-1 - set $CPU=$CPU_STM32 + if ($type==33) + set $CPU=$CPU_STM32M33 + else + set $CPU=$CPU_STM32 + end _setAddressesSTM32 # Enable Trace TRCENA (DCB DEMCR) needed for clocks @@ -1099,12 +1125,12 @@ define enableSTM32TRACE end # Set number of bits in DBGMCU_CR - set *0xE0042004 &= ~(3<<6) + set *($DBGMCUBASE+4) &= ~(3<<6) if ($bits<3) - set *0xE0042004 |= ((($bits+1)<<6) | (1<<5)) + set *($DBGMCUBASE+4) |= ((($bits+1)<<6) | (1<<5)) else - set *0xE0042004 |= ((3<<6) | (1<<5)) + set *$(DBGMCUBASE+4) |= ((3<<6) | (1<<5)) end # Enable Trace TRCENA (DCB DEMCR) @@ -1117,8 +1143,9 @@ define enableSTM32TRACE end document enableSTM32TRACE enableSTM32TRACE : Enable TRACE on STM32 pins - : Number of bits wide (1,2 or 4 only) - : Drive strength (0=lowest, 3=highest) + : Number of bits wide (1,2 or 4 only, default=4) + : Drive strength (0=lowest, 3=highest, default=1) + : Device type, 33=special for CORTEX-M33, otherwise default end # ==================================================================== define enableNRF52TRACE From 4d458fe021051bf72292b73a1bc27d3a9dcebcbe Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Wed, 12 Feb 2025 10:59:53 +0000 Subject: [PATCH 24/46] Update changes to reflect gitlog --- CHANGES.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/CHANGES.md b/CHANGES.md index d345fce9..62815994 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,6 +1,13 @@ Version 2.3.0 In progress * 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) From 3c6c2dcdd33e2bedf31c0876b78e5e0e632da93a Mon Sep 17 00:00:00 2001 From: Jarno Malmari Date: Sat, 16 Nov 2024 18:05:06 +0200 Subject: [PATCH 25/46] Replace various DEMCR TRCENA with a define call --- Support/gdbtrace.init | 51 ++++++++++++++++++++++++------------------- 1 file changed, 29 insertions(+), 22 deletions(-) diff --git a/Support/gdbtrace.init b/Support/gdbtrace.init index 0eb38c26..c97417ad 100644 --- a/Support/gdbtrace.init +++ b/Support/gdbtrace.init @@ -100,6 +100,13 @@ 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 _setAddressesSTM32 # Locations in the memory map for interesting things on STM32 if ($CPU == $CPU_STM32M33) @@ -594,7 +601,7 @@ define prepareSWO set *($ITMBASE+0xfb0) = 0xc5acce55 set *($ETMBASE+0xfb0) = 0xc5acce55 - set *($CDBBASE+0xC)|=(1<<24) + setTRCENA if ($useMan==0) # Use Async mode pin protocol (TPIU_SPPR) @@ -618,7 +625,7 @@ define prepareSWO end # Flush all initial configuration - set *($CDBBASE+0xC)|=(1<<24) + setTRCENA set *($DWTBASE) = 0 set *($ITMBASE+0xe80) = 0 @@ -1103,7 +1110,7 @@ define enableSTM32TRACE _setAddressesSTM32 # Enable Trace TRCENA (DCB DEMCR) needed for clocks - set *($CDBBASE+0xC)=(1<<24) + setTRCENA # Enable compensation cell set *0x40023844 |= (1<<14) @@ -1134,7 +1141,7 @@ define enableSTM32TRACE end # Enable Trace TRCENA (DCB DEMCR) - set *($CDBBASE+0xC)=(1<<24) + setTRCENA # Finally start the trace output _doTRACE @@ -1183,7 +1190,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 +1298,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 +1390,7 @@ define enableTM4C123TRACE end # Enable Trace TRCENA (DCB DEMCR) - set *($CDBBASE+0xC)=(1<<24) + setTRCENA # Finally start the trace output _doTRACE @@ -1505,7 +1512,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 +1583,7 @@ define enableSAMD5XTRACE end # Enable Trace TRCENA (DCB DEMCR) - set *($CDBBASE+0xC)=(1<<24) + setTRCENA # Finally start the trace output _doTRACE @@ -1595,7 +1602,7 @@ define dwtPOSTCNT if ($argc!=1) help dwtPOSTCNT else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<22) else @@ -1615,7 +1622,7 @@ define dwtFOLDEVT if ($argc!=1) help dwtFOLDEVT else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<21) else @@ -1635,7 +1642,7 @@ define dwtLSUEVT if ($argc!=1) help dwtLSUEVT else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<20) else @@ -1655,7 +1662,7 @@ define dwtSLEEPEVT if ($argc!=1) help dwtSLEEPEVT else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<19) else @@ -1675,7 +1682,7 @@ define dwtDEVEVT if ($argc!=1) help dwtDEVEVT else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<18) else @@ -1695,7 +1702,7 @@ define dwtCPIEVT if ($argc!=1) help dwtCPIEVT else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<17) else @@ -1715,7 +1722,7 @@ define dwtTraceException if ($argc!=1) help dwtTraceException else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<16) else @@ -1735,7 +1742,7 @@ define dwtSamplePC if ($argc!=1) help dwtSamplePC else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<12) else @@ -1755,7 +1762,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 +1779,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 +1799,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 +1816,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 +1835,7 @@ define dwtCycEna if ($argc!=1) help dwtCycEna else - set *($CDBBASE+0xC) |= 0x1000000 + setTRCENA if ($arg0==1) set *($DWTBASE) |= (1<<0) else From 3669d9556edf6e0832c06ab7fc51784e196aa1f4 Mon Sep 17 00:00:00 2001 From: Jarno Malmari Date: Sat, 23 Nov 2024 13:15:13 +0200 Subject: [PATCH 26/46] Remove extraneous TRCENA writes to DECMR --- Support/gdbtrace.init | 4 ---- 1 file changed, 4 deletions(-) diff --git a/Support/gdbtrace.init b/Support/gdbtrace.init index c97417ad..2df2c2c9 100644 --- a/Support/gdbtrace.init +++ b/Support/gdbtrace.init @@ -625,7 +625,6 @@ define prepareSWO end # Flush all initial configuration - setTRCENA set *($DWTBASE) = 0 set *($ITMBASE+0xe80) = 0 @@ -1140,9 +1139,6 @@ define enableSTM32TRACE set *$(DBGMCUBASE+4) |= ((3<<6) | (1<<5)) end - # Enable Trace TRCENA (DCB DEMCR) - setTRCENA - # Finally start the trace output _doTRACE From b168db76a609e8c7f5f8e7789f2b9cf8e35769c0 Mon Sep 17 00:00:00 2001 From: Jarno Malmari Date: Fri, 22 Nov 2024 22:17:22 +0200 Subject: [PATCH 27/46] Documentation change for dwtDEVEVT --- Support/gdbtrace.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Support/gdbtrace.init b/Support/gdbtrace.init index 2df2c2c9..25961124 100644 --- a/Support/gdbtrace.init +++ b/Support/gdbtrace.init @@ -1689,7 +1689,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 From 3b4f5f0576b3db7dda5ede6b0b515c75f6be49f7 Mon Sep 17 00:00:00 2001 From: Jarno Malmari Date: Sat, 23 Nov 2024 13:00:20 +0200 Subject: [PATCH 28/46] Introduce unlockComponent --- Support/gdbtrace.init | 52 +++++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 24 deletions(-) diff --git a/Support/gdbtrace.init b/Support/gdbtrace.init index 25961124..cc1d956b 100644 --- a/Support/gdbtrace.init +++ b/Support/gdbtrace.init @@ -107,6 +107,10 @@ 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) @@ -279,12 +283,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 @@ -368,7 +372,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) @@ -598,8 +602,8 @@ define prepareSWO end # Make sure we can get to everything - set *($ITMBASE+0xfb0) = 0xc5acce55 - set *($ETMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ITMBASE + unlockComponent $ETMBASE setTRCENA @@ -852,10 +856,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. @@ -865,7 +869,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 @@ -1012,7 +1016,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) @@ -1852,7 +1856,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 @@ -1869,7 +1873,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 @@ -1888,7 +1892,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 @@ -1905,7 +1909,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 @@ -1926,7 +1930,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 @@ -1947,7 +1951,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 @@ -1968,7 +1972,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 @@ -1988,7 +1992,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 @@ -2008,7 +2012,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 @@ -2024,7 +2028,7 @@ define ITMTPR if ($argc!=1) help ITMTPR else - set *($ITMBASE+0xfb0) = 0xc5acce55 + unlockComponent $ITMBASE set *($ITMBASE+0xe40) = $arg0 end @@ -2040,7 +2044,7 @@ define tracetest if ($argc!=1) help tracetest else - set *($TPIUBASE+0xfb0) = 0xc5acce55 + unlockComponent $TPIUBASE if ($arg0 == 0) set *($TPIUBASE+0x204) = 0 else From 2780ddc887e8805545abe03e50043b284f6e2ae9 Mon Sep 17 00:00:00 2001 From: Jarno Malmari Date: Sat, 23 Nov 2024 13:24:11 +0200 Subject: [PATCH 29/46] Unlock DWT instead of ETM in prepareSWO --- Support/gdbtrace.init | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Support/gdbtrace.init b/Support/gdbtrace.init index cc1d956b..5870be0a 100644 --- a/Support/gdbtrace.init +++ b/Support/gdbtrace.init @@ -603,7 +603,7 @@ define prepareSWO # Make sure we can get to everything unlockComponent $ITMBASE - unlockComponent $ETMBASE + unlockComponent $DWTBASE setTRCENA From f30eadfb5ff544ff7f6f0a99afbe5708a1d72d67 Mon Sep 17 00:00:00 2001 From: Jarno Malmari Date: Mon, 17 Feb 2025 20:07:41 +0200 Subject: [PATCH 30/46] Fix M33 type detection --- Support/gdbtrace.init | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Support/gdbtrace.init b/Support/gdbtrace.init index 5870be0a..b317483a 100644 --- a/Support/gdbtrace.init +++ b/Support/gdbtrace.init @@ -1095,8 +1095,8 @@ define enableSTM32TRACE set $drive = $arg1 end - if $type >= 3 - set $drive = $arg2 + if $argc >= 3 + set $type = $arg2 end if ($drive > 3) From ba06b1ca45f7a98e6a0b2c4749e1e4d3d162aded Mon Sep 17 00:00:00 2001 From: Jarno Malmari Date: Sat, 23 Nov 2024 13:06:40 +0200 Subject: [PATCH 31/46] Add support for STM32H7 in gdbtrace.init --- Support/gdbtrace.init | 196 +++++++++++++++++++++++++++++------------- 1 file changed, 136 insertions(+), 60 deletions(-) diff --git a/Support/gdbtrace.init b/Support/gdbtrace.init index b317483a..edefc70e 100644 --- a/Support/gdbtrace.init +++ b/Support/gdbtrace.init @@ -81,7 +81,7 @@ end # Definitions for the CPU types we currently support set $CPU_IMXRT102X=1 -set $CPU_STM32=2 +set $CPU_STM32F1F4F7=2 set $CPU_IMXRT106X=1 set $CPU_NRF=3 set $CPU_EFR32=4 @@ -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 @@ -113,14 +114,47 @@ 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 + end end define _setAddressesIMXRT @@ -605,27 +639,37 @@ define prepareSWO unlockComponent $ITMBASE unlockComponent $DWTBASE + 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 @@ -899,37 +943,47 @@ 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 @@ -1030,15 +1084,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) @@ -1082,7 +1132,7 @@ define enableSTM32TRACE set $bits=4 set $drive=1 - set $type=1 + set $dev=0 if $argc >= 1 set $bits = $arg0 @@ -1096,7 +1146,7 @@ define enableSTM32TRACE end if $argc >= 3 - set $type = $arg2 + set $dev = $arg2 end if ($drive > 3) @@ -1105,19 +1155,33 @@ 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 setTRCENA - # Enable compensation cell - set *0x40023844 |= (1<<14) - set *0x40013820 |=1 + if $CPU == $CPU_STM32H7 + # Enable TRACECKEN, D1DBGCKEN + set *$DBGMCU_CR |= 7 | (3 << 20) + + 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 + # Enable compensation cell + set *0x40023844 |= (1<<14) + set *0x40013820 |=1 + end # Setup PE2 & PE3 enableSTM32Pin 4 2 $drive @@ -1134,17 +1198,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 # 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 From d8091e8aa3ab094612de8017d591da16aefa3555 Mon Sep 17 00:00:00 2001 From: loebl Date: Mon, 24 Feb 2025 15:28:20 +0100 Subject: [PATCH 32/46] Correct local timestamp decoding The bug was a simple oversight, a missing bitmask, probably due to a copy paste error. Reformatted the three checks to be serial, so the pattern of the code better emerges and differences are easier to spot. Found this by emitting packages which should occur basically exactly every 250 microseconds (160MHz, 39999 ticks), but orbuculum decoded it to 350 (56383 ticks). The difference is 16384 ticks, so this lead me to the parsing code. --- Src/msgDecoder.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/Src/msgDecoder.c b/Src/msgDecoder.c index 8245a3f3..5379d5e0 100644 --- a/Src/msgDecoder.c +++ b/Src/msgDecoder.c @@ -207,17 +207,15 @@ static bool _handleTS( struct ITMPacket *packet, struct TSMsg *decoded ) if ( packet->len > 2 ) { - stamp |= ( packet->d[2] ) << 7; - - if ( packet->len > 3 ) - { - stamp |= ( packet->d[3] & 0x7F ) << 14; - - if ( packet->len > 4 ) - { - stamp |= ( packet->d[4] & 0x7f ) << 21; - } - } + stamp |= ( packet->d[2] & 0x7F ) << 7; + } + if ( packet->len > 3 ) + { + stamp |= ( packet->d[3] & 0x7F ) << 14; + } + if ( packet->len > 4 ) + { + stamp |= ( packet->d[4] & 0x7f ) << 21; } } From 3c4d34690319d9c10aa8a7873fdde06535be6b64 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Thu, 27 Feb 2025 17:29:33 +0000 Subject: [PATCH 33/46] Extend from-target timestamping to 1/10us resolution --- CHANGES.md | 1 + Src/orbcat.c | 8 +++++--- 2 files changed, 6 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 62815994..d2eb3986 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,5 @@ Version 2.3.0 In progress +* 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 diff --git a/Src/orbcat.c b/Src/orbcat.c index 66951182..75eabfa5 100644 --- a/Src/orbcat.c +++ b/Src/orbcat.c @@ -46,7 +46,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 +218,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 { From 6b4a6984b4b255c89a08628b1fbb86fddb34f990 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Fri, 14 Mar 2025 23:21:05 +0000 Subject: [PATCH 34/46] Fix M33 parallel trace handling config --- Support/gdbtrace.init | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Support/gdbtrace.init b/Support/gdbtrace.init index edefc70e..9d1d58b3 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_STM32F1F4F7=2 set $CPU_IMXRT106X=1 +set $CPU_STM32F1F4F7=2 set $CPU_NRF=3 set $CPU_EFR32=4 set $CPU_TM4C=5 @@ -921,8 +921,6 @@ define enableIMXRT117XSWO #set language auto end -# ==================================================================== - define enableKinetisSWO _setAddressesKinetis set language c @@ -940,6 +938,8 @@ define enableKinetisSWO set language auto end +# ==================================================================== + define enableSTM32SWO #set language c @@ -960,7 +960,7 @@ define enableSTM32SWO enableSTM32Pin 1 3 3 end - if $CPU == $CPU_STM32F1F4F7 + if ($CPU == $CPU_STM32F1F4F7) if (($dev==4) || ($dev==7)) # STM32F4/7 variant: SWO on PB3. enableSTM32Pin 1 3 3 @@ -1160,7 +1160,7 @@ define enableSTM32TRACE # Enable Trace TRCENA (DCB DEMCR) needed for clocks setTRCENA - if $CPU == $CPU_STM32H7 + if ($CPU == $CPU_STM32H7) # Enable TRACECKEN, D1DBGCKEN set *$DBGMCU_CR |= 7 | (3 << 20) @@ -1178,9 +1178,11 @@ define enableSTM32TRACE # Enable both ETM and ITM in trace funnel. bit0=ETM, bit1=ITM set *($CSTFBASE + 0x000) |= 3 else - # Enable compensation cell - set *0x40023844 |= (1<<14) - set *0x40013820 |=1 + if $CPU != $CPU_STM32M33 + # Enable compensation cell + set *($RRCGPIO+0x14) |= (1<<14) + set *0x40013820 |=1 + end end # Setup PE2 & PE3 From 6a21590915872b75570c0fb8b95192d4aff4bed2 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Fri, 14 Mar 2025 23:46:34 +0000 Subject: [PATCH 35/46] Fix all code to have more sensible differentiation between stdout and stderr --- Inc/generics.h | 3 +- Src/generics.c | 28 ++++++------- Src/msgDecoder.c | 2 + Src/orbcat.c | 52 ++++++++++++------------ Src/orbdump.c | 26 ++++++------ Src/orbfifo.c | 30 +++++++------- Src/orblcd.c | 28 ++++++------- Src/orbmortem.c | 50 +++++++++++------------ Src/orbprofile.c | 44 ++++++++++---------- Src/orbstat.c | 42 +++++++++---------- Src/orbtop.c | 104 +++++++++++++++++++++++------------------------ Src/orbtrace.c | 52 ++++++++++++------------ Src/orbtraceIf.c | 10 ++--- Src/orbuculum.c | 62 ++++++++++++++-------------- Src/orbzmq.c | 42 +++++++++---------- 15 files changed, 289 insertions(+), 286 deletions(-) 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/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/msgDecoder.c b/Src/msgDecoder.c index 5379d5e0..610b7092 100644 --- a/Src/msgDecoder.c +++ b/Src/msgDecoder.c @@ -209,10 +209,12 @@ static bool _handleTS( struct ITMPacket *packet, struct TSMsg *decoded ) { stamp |= ( packet->d[2] & 0x7F ) << 7; } + if ( packet->len > 3 ) { stamp |= ( packet->d[3] & 0x7F ) << 14; } + if ( packet->len > 4 ) { stamp |= ( packet->d[4] & 0x7f ) << 21; diff --git a/Src/orbcat.c b/Src/orbcat.c index 75eabfa5..4a4df608 100644 --- a/Src/orbcat.c +++ b/Src/orbcat.c @@ -248,7 +248,7 @@ static void _outputText( char *p ) if ( !_r.inLine ) { _printTimestamp( opConstruct ); - genericsPrintf( "%s", opConstruct ); + genericsFPrintf( stdout, "%s", opConstruct ); _r.inLine = true; } @@ -258,21 +258,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; } @@ -298,7 +298,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; } @@ -312,7 +312,7 @@ void _expex( const char *fmt, ... ) if ( !_r.inLine ) { - genericsPrintf( "%s", _r.dwtText ); + genericsFPrintf( stdout, "%s", _r.dwtText ); _r.dwtText[0] = 0; } } @@ -551,30 +551,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[] = @@ -991,7 +991,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..bae2e8de 100644 --- a/Src/orbdump.c +++ b/Src/orbdump.c @@ -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 index 78803583..058881a3 100644 --- a/Src/orbfifo.c +++ b/Src/orbfifo.c @@ -71,26 +71,26 @@ struct 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 ); + genericsFPrintf( stderr, "Usage: %s [options]" EOL, progName ); + genericsFPrintf( stderr, " -b, --basedir: for channels" EOL ); + genericsFPrintf( stderr, " -c, --channel: ,, of channel to populate (repeat per channel)" 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, " -P, --permanent: Create permanent files rather than fifos" 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, " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); + genericsFPrintf( stderr, " -V, --version: Print version and exit" EOL ); + genericsFPrintf( stderr, " -W, --writer-path: Enable filewriter functionality using specified base path" EOL ); } // ==================================================================================================== void _printVersion( void ) { - genericsPrintf( "orbfifo version " GIT_DESCRIBE ); + genericsFPrintf( stderr, "orbfifo version " GIT_DESCRIBE ); } // ==================================================================================================== struct option _longOptions[] = diff --git a/Src/orblcd.c b/Src/orblcd.c index 0bb6856e..6f12c9bd 100644 --- a/Src/orblcd.c +++ b/Src/orblcd.c @@ -422,26 +422,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..d49ae454 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[] = diff --git a/Src/orbprofile.c b/Src/orbprofile.c index 6bbfe68c..c9dc6f36 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[] = 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..3d58b0ba 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 ); } @@ -721,19 +721,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 +755,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 +767,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 +1612,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 ) From 72e4997f593c3aef84ef799ef171d561564ca1c0 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Fri, 14 Mar 2025 23:53:17 +0000 Subject: [PATCH 36/46] Documentation update addressing issues #160 and #161 --- Docs/BlackMagicProbe-Interface | 5 +---- README.md | 2 +- 2 files changed, 2 insertions(+), 5 deletions(-) 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/README.md b/README.md index d22a58e2..195cc3a9 100644 --- a/README.md +++ b/README.md @@ -275,7 +275,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: From 45c0cd8d36d8bfabda4cf2fef47972e206a8ff60 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Fri, 28 Mar 2025 09:18:55 +0000 Subject: [PATCH 37/46] Make enableSTM32TRACE have sensible default --- Support/gdbtrace.init | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Support/gdbtrace.init b/Support/gdbtrace.init index 9d1d58b3..fc0c8513 100644 --- a/Support/gdbtrace.init +++ b/Support/gdbtrace.init @@ -154,6 +154,7 @@ define _setAddressesSTM32 set $GPIOBASE = 0x40020000 set $RCCGPIO = 0x40023830 set $DBGMCU_CR = 0xE0042004 + set $RRCGPIO = 0x40023830 end end @@ -1132,7 +1133,7 @@ define enableSTM32TRACE set $bits=4 set $drive=1 - set $dev=0 + set $dev=1 if $argc >= 1 set $bits = $arg0 @@ -1160,6 +1161,7 @@ define enableSTM32TRACE # Enable Trace TRCENA (DCB DEMCR) needed for clocks setTRCENA + if ($CPU == $CPU_STM32H7) # Enable TRACECKEN, D1DBGCKEN set *$DBGMCU_CR |= 7 | (3 << 20) From f86a2e4c5fd07df1e556981ca223dd9dde0aa89f Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Mon, 31 Mar 2025 09:27:16 +0100 Subject: [PATCH 38/46] Improve lcd handling for ETC --- Inc/orblcd_protocol.h | 9 +++++++-- Src/orblcd.c | 9 ++++++++- 2 files changed, 15 insertions(+), 3 deletions(-) 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/Src/orblcd.c b/Src/orblcd.c index 6f12c9bd..59dd1038 100644 --- a/Src/orblcd.c +++ b/Src/orblcd.c @@ -127,7 +127,14 @@ static void _paintPixels( struct swMsg *m, struct RunTime *r ) 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 ) ) { From 5010b16b68b06079af519de4adf77ce59b96ceee Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Wed, 2 Apr 2025 08:53:11 +0100 Subject: [PATCH 39/46] Fix url formation for server and port --- Src/orbuculum.c | 1 + 1 file changed, 1 insertion(+) diff --git a/Src/orbuculum.c b/Src/orbuculum.c index 3d58b0ba..316ab22e 100644 --- a/Src/orbuculum.c +++ b/Src/orbuculum.c @@ -544,6 +544,7 @@ bool _processOptions( int argc, char *argv[], struct RunTime *r ) if ( *a == ':' ) { + *a = 0; r->options->nwserverPort = atoi( ++a ); } From 5cf45fa97f119bd113a09965f4a099e56abe37bb Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Thu, 17 Apr 2025 15:05:23 +0100 Subject: [PATCH 40/46] Increase max string length in a single packet --- Src/orbcat.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Src/orbcat.c b/Src/orbcat.c index 4a4df608..dcffb855 100644 --- a/Src/orbcat.c +++ b/Src/orbcat.c @@ -30,7 +30,7 @@ #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 */ From 36683d366ddb376b2c4f612d6ad553e11ba4e014 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Mon, 21 Apr 2025 17:28:15 +0100 Subject: [PATCH 41/46] Add documentation for orbcat 'exceptions' option --- README.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 195cc3a9..7a29d1bd 100644 --- a/README.md +++ b/README.md @@ -716,7 +716,8 @@ options for orbcat are; `-w, --window [string]`: Title for on-screen window. - + `-x, --exceptions`: Include exception information in output, in time order + Orbtop ------ From 6b5bb9c6e6495d55b218bb8081fa01b4bfe2407f Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Mon, 21 Apr 2025 19:35:36 +0100 Subject: [PATCH 42/46] Remove orbfifo from build as its no longer relevant --- README.md | 77 +---- Src/itmfifos.c | 835 ----------------------------------------------- Src/orbcat.c | 1 - Src/orbdump.c | 2 +- Src/orbfifo.c | 549 ------------------------------- Src/orbmortem.c | 2 +- Src/orbprofile.c | 2 +- meson.build | 15 - 8 files changed, 4 insertions(+), 1479 deletions(-) delete mode 100644 Src/itmfifos.c delete mode 100644 Src/orbfifo.c diff --git a/README.md b/README.md index 7a29d1bd..0da7bf84 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. @@ -412,7 +410,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 +472,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. 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/orbcat.c b/Src/orbcat.c index dcffb855..81ac7fc4 100644 --- a/Src/orbcat.c +++ b/Src/orbcat.c @@ -28,7 +28,6 @@ #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*4) /* Maximum length that will be output */ #define DEFAULT_TS_TRIGGER '\n' /* Default trigger character for timestamp output */ diff --git a/Src/orbdump.c b/Src/orbdump.c index bae2e8de..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 diff --git a/Src/orbfifo.c b/Src/orbfifo.c deleted file mode 100644 index 058881a3..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 ) - -{ - genericsFPrintf( stderr, "Usage: %s [options]" EOL, progName ); - genericsFPrintf( stderr, " -b, --basedir: for channels" EOL ); - genericsFPrintf( stderr, " -c, --channel: ,, of channel to populate (repeat per channel)" 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, " -P, --permanent: Create permanent files rather than fifos" 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, " -v, --verbose: Verbose mode 0(errors)..3(debug)" EOL ); - genericsFPrintf( stderr, " -V, --version: Print version and exit" EOL ); - genericsFPrintf( stderr, " -W, --writer-path: Enable filewriter functionality using specified base path" EOL ); -} -// ==================================================================================================== -void _printVersion( void ) - -{ - genericsFPrintf( stderr, "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/orbmortem.c b/Src/orbmortem.c index d49ae454..495e2c76 100644 --- a/Src/orbmortem.c +++ b/Src/orbmortem.c @@ -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 c9dc6f36..2841c177 100644 --- a/Src/orbprofile.c +++ b/Src/orbprofile.c @@ -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/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', From ceec063a595892b1fcb477707ae4778d0b8a0e88 Mon Sep 17 00:00:00 2001 From: Dave Marples Date: Fri, 1 Aug 2025 09:39:46 +0100 Subject: [PATCH 43/46] Orblcd now accomodates short messages --- CHANGES.md | 1 + README.md | 15 ++++++++++++--- Src/orblcd.c | 3 ++- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index d2eb3986..a27bdca4 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,5 @@ 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) diff --git a/README.md b/README.md index 0da7bf84..cccb5d64 100644 --- a/README.md +++ b/README.md @@ -243,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 ----- diff --git a/Src/orblcd.c b/Src/orblcd.c index 59dd1038..51495d3b 100644 --- a/Src/orblcd.c +++ b/Src/orblcd.c @@ -122,7 +122,8 @@ 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 ) ) { From 7a6ba3130811f12ea09db415d0cd6e31ee3e9d95 Mon Sep 17 00:00:00 2001 From: Lukas Ostendorf Date: Wed, 10 Dec 2025 21:58:57 +0100 Subject: [PATCH 44/46] Fix: define correct mask for interrupts orbstat detects interrupts by comparing LR values to the SPECIALS_MASK. Correct the mask to fit also armv8-m and armv7-m architecture. --- Inc/symbols.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 }; From 11b98caec897a5231178decf5f602adfbf982de6 Mon Sep 17 00:00:00 2001 From: Jarno Malmari Date: Sat, 31 Jan 2026 12:26:01 +0200 Subject: [PATCH 45/46] Fix styling issue in udev rules This was not preventing the rule to load but did cause a warning. --- Support/60-orbcode.rules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Support/60-orbcode.rules b/Support/60-orbcode.rules index 1501072c..c03cfb7a 100644 --- a/Support/60-orbcode.rules +++ b/Support/60-orbcode.rules @@ -5,8 +5,8 @@ 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" +ATTRS{idVendor}=="1209", ATTRS{idProduct}=="3442", GROUP="plugdev", TAG+="uaccess" # Orbrace mini -ATTRS{idVendor}=="1209" ATTRS{idProduct}=="3443", GROUP="plugdev", TAG+="uaccess" +ATTRS{idVendor}=="1209", ATTRS{idProduct}=="3443", GROUP="plugdev", TAG+="uaccess" LABEL="orb_rules_end" From 3de6b9b8afcedfe6d90604a7990fbd2c13879f5e Mon Sep 17 00:00:00 2001 From: Jarno Malmari Date: Sat, 31 Jan 2026 12:26:20 +0200 Subject: [PATCH 46/46] Fix typo in udev rules --- Support/60-orbcode.rules | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Support/60-orbcode.rules b/Support/60-orbcode.rules index c03cfb7a..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 +# Orbtrace mini in bootloader mode ATTRS{idVendor}=="1209", ATTRS{idProduct}=="3442", GROUP="plugdev", TAG+="uaccess" -# Orbrace mini +# Orbtrace mini ATTRS{idVendor}=="1209", ATTRS{idProduct}=="3443", GROUP="plugdev", TAG+="uaccess" LABEL="orb_rules_end"