@@ -307,11 +307,9 @@ int bmp_break(void)
307307 * The name of the driver for the MCU (that the Black Magic Probe uses) is
308308 * returned.
309309 *
310- * \param tpwr Set to 1 to power up the voltage-sense pin, 0 to
311- * power-down, or 2 to optionally power this pin if the
312- * initial scan returns a power of 0.0V.
313- * \param connect_srst Set to 1 to let the Black Magic Probe keep the target
314- * MCU in reset while scanning and attaching.
310+ * \param autopower If set, and if the swdp_scan command returns 0V power,
311+ * the "tpwr" command is given, before the swdp_scan
312+ * command is retried.
315313 * \param name Will be set to the name of the driver for the MCU (the
316314 * MCU series name) on output. This parameter may be NULL.
317315 * \param namelength The maximum length of the name, including the \0 byte.
@@ -322,10 +320,10 @@ int bmp_break(void)
322320 * \param archlength The maximum length of the architecture name, including
323321 * the \0 byte.
324322 *
325- * \return 1 on success, 0 on failure. Status and error messages are passed via
326- * the callback.
323+ * \return true on success, false on failure. Status and error messages are
324+ * passed via the callback.
327325 */
328- int bmp_attach (int tpwr , int connect_srst , char * name , size_t namelength , char * arch , size_t archlength )
326+ bool bmp_attach (bool autopower , char * name , size_t namelength , char * arch , size_t archlength )
329327{
330328 char buffer [512 ];
331329 size_t size ;
@@ -338,39 +336,33 @@ int bmp_attach(int tpwr, int connect_srst, char *name, size_t namelength, char *
338336
339337 if (!bmp_isopen ()) {
340338 notice (BMPERR_ATTACHFAIL , "No connection to debug probe" );
341- return 0 ;
339+ return false ;
342340 }
343341
344342restart :
345- if (connect_srst != 0 ) {
346- if (!bmp_monitor ("connect_srst enable" ))
347- notice (BMPERR_MONITORCMD , "Setting connect-with-reset option failed" );
348- }
349- if (tpwr == 1 ) {
350- if (bmp_monitor ("tpwr enable" )) {
351- /* give the micro-controller a bit of time to start up, before issuing
352- the swdp_scan command */
353- # if defined _WIN32
354- Sleep (100 );
355- # else
356- usleep (100 * 1000 );
357- # endif
358- } else {
359- notice (BMPERR_MONITORCMD , "Power to target failed" );
360- }
361- }
362343 gdbrsp_xmit ("qRcmd,swdp_scan" , -1 );
363344 for ( ;; ) {
364345 size = gdbrsp_recv (buffer , sizearray (buffer ), 1000 );
365346 if (size > 2 && buffer [0 ] == 'o' ) {
366347 const char * ptr ;
367348 buffer [size ] = '\0' ;
368349 /* parse the string */
369- if (tpwr == 2 && strchr (buffer , '\n' ) != NULL && (ptr = strstr (buffer + 1 , "voltage:" )) != NULL ) {
350+ if (autopower && strchr (buffer , '\n' ) != NULL && (ptr = strstr (buffer + 1 , "voltage:" )) != NULL ) {
370351 double voltage = strtod (ptr + 8 , (char * * )& ptr );
371352 if (* ptr == 'V' && voltage < 0.1 ) {
372353 notice (BMPSTAT_NOTICE , "Note: powering target" );
373- tpwr = 1 ;
354+ if (bmp_monitor ("tpwr enable" )) {
355+ /* give the micro-controller a bit of time to start up, before issuing
356+ the swdp_scan command */
357+ # if defined _WIN32
358+ Sleep (100 );
359+ # else
360+ usleep (100 * 1000 );
361+ # endif
362+ } else {
363+ notice (BMPERR_MONITORCMD , "Power to target failed" );
364+ }
365+ autopower = false; /* do not drop in this case again */
374366 goto restart ;
375367 }
376368 }
@@ -394,7 +386,7 @@ int bmp_attach(int tpwr, int connect_srst, char *name, size_t namelength, char *
394386 notice (BMPSTAT_NOTICE , buffer + 1 ); /* skip the 'o' at the start */
395387 } else if (size != 2 || memcmp (buffer , "OK" , size ) != 0 ) {
396388 /* error message was already given by an "output"-response */
397- return 0 ;
389+ return false ;
398390 } else {
399391 break ; /* OK was received */
400392 }
@@ -407,7 +399,7 @@ int bmp_attach(int tpwr, int connect_srst, char *name, size_t namelength, char *
407399 || (size >= 3 && buffer [0 ] == 'T' && isxdigit (buffer [1 ]) && isxdigit (buffer [2 ]));
408400 if (!ok ) {
409401 notice (BMPERR_ATTACHFAIL , "Attach failed" );
410- return 0 ;
402+ return false ;
411403 }
412404 notice (BMPSTAT_NOTICE , "Attached to target 1" );
413405
@@ -443,26 +435,26 @@ int bmp_attach(int tpwr, int connect_srst, char *name, size_t namelength, char *
443435 if (FlashRgnCount == 0 )
444436 notice (BMPERR_NOFLASH , "No Flash memory record" );
445437
446- return 1 ;
438+ return true ;
447439}
448440
449- int bmp_detach (int powerdown )
441+ bool bmp_detach (bool powerdown )
450442{
451- int result = 0 ;
443+ bool result = false ;
452444
453445 if (bmp_isopen ()) {
454446 char buffer [100 ];
455447 size_t size ;
456- result = 1 ;
448+ result = true ;
457449 /* detach */
458450 gdbrsp_xmit ("D" , -1 );
459451 size = gdbrsp_recv (buffer , sizearray (buffer ), 1000 );
460452 if (size != 2 || memcmp (buffer , "OK" , size ) != 0 )
461- result = 0 ;
453+ result = false ;
462454 /* optionally disable power */
463455 if (powerdown ) {
464456 if (!bmp_monitor ("tpwr disable" ))
465- result = 0 ;
457+ result = false ;
466458 }
467459 }
468460
@@ -516,6 +508,163 @@ int bmp_checkversionstring(void)
516508 return probe ;
517509}
518510
511+ /** bmp_get_monitor_cmds() collects the list of "monitor" commands. These are
512+ * probe-dependent and target-dependent (plus probe firmware version
513+ * dependent).
514+ *
515+ * When this function is called after connecting to the probe (but before
516+ * attaching to the target), it returns only the probe-dependent commands.
517+ *
518+ * \return A pointer to a dynamically allocated string, which contains the
519+ * commands separated by a space. The returned list must be freed with
520+ * free().
521+ */
522+ const char * bmp_get_monitor_cmds (void )
523+ {
524+ if (!bmp_isopen ())
525+ return NULL ;
526+
527+ int count = 0 ;
528+ int listsize = 4 ;
529+ char * * list = malloc (listsize * sizeof (char * ));
530+ if (list == NULL )
531+ return NULL ;
532+ memset (list , 0 , listsize * sizeof (char * ));
533+
534+ char line [512 ];
535+ memset (line , 0 , sizeof line );
536+
537+ gdbrsp_xmit ("qRcmd,help" ,-1 );
538+ for (;;) {
539+ char buffer [512 ];
540+ size_t size = gdbrsp_recv (buffer , sizearray (buffer ) - 1 , 1000 );
541+ if (size > 0 ) {
542+ assert (size < sizearray (buffer ));
543+ buffer [size ] = '\0' ;
544+ char * ptr ;
545+ if (buffer [0 ] == 'o' ) {
546+ if (line [0 ] == 'o' )
547+ strlcat (line , buffer + 1 , sizearray (line ));
548+ else
549+ strlcpy (line , buffer , sizearray (line ));
550+ if (strchr (line , '\n' ) != NULL ) {
551+ /* get only the command (strip summary) */
552+ char * ptr = strstr (line , "--" );
553+ if (ptr != NULL ) {
554+ while (ptr > line && * (ptr - 1 ) <= ' ' )
555+ ptr -= 1 ;
556+ * ptr = '\0' ;
557+ /* check whether to grow the list */
558+ if (count + 1 >= listsize ) {
559+ int newsize = 2 * listsize ;
560+ char * * newlist = malloc (newsize * sizeof (char * ));
561+ if (newlist != NULL ) {
562+ memset (newlist , 0 , newsize * sizeof (char * ));
563+ memcpy (newlist , list , count * sizeof (char * ));
564+ free ((void * )list );
565+ list = newlist ;
566+ listsize = newsize ;
567+ }
568+ }
569+ if (count + 1 < listsize ) {
570+ ptr = line + 1 ; /* skip 'o' that starts the line of the reply */
571+ while (* ptr != '\0' && * ptr <= ' ' )
572+ ptr ++ ; /* skip whitespace too */
573+ list [count ]= strdup (ptr );
574+ count ++ ;
575+ }
576+ }
577+ memset (line , 0 , sizeof line );
578+ }
579+ } else if ((ptr = strchr (buffer , 'o' )) != NULL ) {
580+ strlcpy (line , ptr , sizearray (line ));
581+ } else if (size == 2 && memcmp (buffer , "OK" , size ) == 0 ) {
582+ /* end response found -> done */
583+ break ;
584+ }
585+ } else {
586+ /* no new data arrived within the time-out, assume failure */
587+ break ;
588+ }
589+ }
590+
591+ /* sort the retrieved list (insertion sort) */
592+ for (int i = 1 ; i < count ; i ++ ) {
593+ char * key = list [i ];
594+ int j ;
595+ for (j = i ; j > 0 && strcmp (list [j - 1 ], key ) > 0 ; j -- )
596+ list [j ] = list [j - 1 ];
597+ list [j ] = key ;
598+ }
599+
600+ /* build a string from the list */
601+ size_t total_length = 0 ;
602+ for (int idx = 0 ; idx < count ; idx ++ ) {
603+ assert (list [idx ] != NULL );
604+ total_length += strlen (list [idx ]) + 1 ; /* +1 for space between words, or for final '\0' */
605+ }
606+ char * buffer = malloc (total_length * sizeof (char ));
607+ if (buffer != NULL ) {
608+ * buffer = '\0' ;
609+ for (int idx = 0 ; idx < count ; idx ++ ) {
610+ assert (list [idx ] != NULL );
611+ strcat (buffer , list [idx ]);
612+ if (idx + 1 < count )
613+ strcat (buffer , " " );
614+ }
615+ }
616+
617+ /* clean up */
618+ for (int idx = 0 ; idx < count ; idx ++ ) {
619+ assert (list [idx ] != NULL );
620+ free ((void * )list [idx ]);
621+ }
622+ free (list );
623+
624+ return (const char * )buffer ;
625+ }
626+
627+ /** bmp_expand_monitor_cmd() finds the complete command from a prefix.
628+ * \param buffer [out] Will contain the complete command.
629+ * \param bufsize The size of the output buffer.
630+ * \param name [in] The prefix to complete.
631+ * \param list [in] A string with all commands (separated by spaces).
632+ * \return true on success, false if the prefix does not match any command.
633+ */
634+ bool bmp_expand_monitor_cmd (char * buffer , size_t bufsize , const char * name , const char * list )
635+ {
636+ assert (buffer != NULL && bufsize != 0 );
637+ assert (name != NULL );
638+ assert (list != NULL );
639+ size_t name_len = strlen (name );
640+
641+ buffer [0 ] = '\0' ;
642+ const char * head = list ;
643+ while (* head != '\0' ) {
644+ /* the assumption is that the list of commands is "wekk-formed": no leading
645+ or trailing spaces and the tokens separated by a single space */
646+ assert (* head > ' ' );
647+ const char * tail = strchr (head , ' ' );
648+ if (tail == NULL )
649+ tail = head + strlen (head );
650+ size_t token_len = tail - head ;
651+ if (token_len >= name_len && strncmp (name , head , name_len ) == 0 ) {
652+ /* match, copy the token */
653+ assert (token_len < bufsize );
654+ if (bufsize <= token_len )
655+ token_len = bufsize - 1 ;
656+ strncpy (buffer , head , token_len );
657+ buffer [token_len ] = '\0' ;
658+ return true;
659+ }
660+ head = tail ;
661+ while (* head != '\0' && * head <= ' ' )
662+ head ++ ;
663+ }
664+
665+ return false;
666+ }
667+
519668/** bmp_monitor() executes a "monitor" command and returns whether the reply
520669 * indicates success. This is suitable for simple monitor commands, that do
521670 * not require analysis of the reply strings sent by the device (other than
0 commit comments