1 /* Remote debugging interface for Hitachi HMS Monitor Version 1.0
2 Copyright 1992 Free Software Foundation, Inc.
3 Contributed by Cygnus Support. Written by Steve Chamberlain
6 This file is part of GDB.
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
36 /* External data declarations */
37 extern int stop_soon_quietly
; /* for wait_for_inferior */
39 /* Forward data declarations */
40 extern struct target_ops hms_ops
; /* Forward declaration */
42 /* Forward function declarations */
43 static void hms_fetch_registers ();
44 static int hms_store_registers ();
45 static void hms_close ();
46 static int hms_clear_breakpoints();
48 extern struct target_ops hms_ops
;
52 /***********************************************************************/
53 /* Caching stuff stolen from remote-nindy.c */
55 /* The data cache records all the data read from the remote machine
56 since the last time it stopped.
58 Each cache block holds LINE_SIZE bytes of data
59 starting at a multiple-of-LINE_SIZE address. */
62 #define LINE_SIZE_POWER 4
63 #define LINE_SIZE (1<<LINE_SIZE_POWER) /* eg 1<<3 == 8 */
64 #define LINE_SIZE_MASK ((LINE_SIZE-1)) /* eg 7*2+1= 111*/
65 #define DCACHE_SIZE 64 /* Number of cache blocks */
66 #define XFORM(x) ((x&LINE_SIZE_MASK)>>2)
68 struct dcache_block
*next
, *last
;
69 unsigned int addr
; /* Address for which data is recorded. */
70 int data
[LINE_SIZE
/sizeof(int)];
73 struct dcache_block dcache_free
, dcache_valid
;
75 /* Free all the data cache blocks, thus discarding all cached data. */
80 register struct dcache_block
*db
;
82 while ((db
= dcache_valid
.next
) != &dcache_valid
)
85 insque (db
, &dcache_free
);
90 * If addr is present in the dcache, return the address of the block
98 register struct dcache_block
*db
;
103 /* Search all cache blocks for one that is at this address. */
104 db
= dcache_valid
.next
;
105 while (db
!= &dcache_valid
)
107 if ((addr
& ~LINE_SIZE_MASK
)== db
->addr
)
114 /* Return the int data at address ADDR in dcache block DC. */
117 dcache_value (db
, addr
)
118 struct dcache_block
*db
;
123 return (db
->data
[XFORM(addr
)]);
126 /* Get a free cache block, put or keep it on the valid list,
127 and return its address. The caller should store into the block
128 the address and data that it describes, then remque it from the
129 free list and insert it into the valid list. This procedure
130 prevents errors from creeping in if a ninMemGet is interrupted
131 (which used to put garbage blocks in the valid list...). */
133 struct dcache_block
*
136 register struct dcache_block
*db
;
138 if ((db
= dcache_free
.next
) == &dcache_free
)
140 /* If we can't get one from the free list, take last valid and put
141 it on the free list. */
142 db
= dcache_valid
.last
;
144 insque (db
, &dcache_free
);
148 insque (db
, &dcache_valid
);
152 /* Return the contents of the word at address ADDR in the remote machine,
153 using the data cache. */
159 register struct dcache_block
*db
;
161 db
= dcache_hit (addr
);
164 db
= dcache_alloc ();
166 hms_read_inferior_memory(addr
& ~LINE_SIZE_MASK
, (unsigned char *)db
->data
, LINE_SIZE
);
168 db
->addr
= addr
& ~LINE_SIZE_MASK
;
169 remque (db
); /* Off the free list */
170 insque (db
, &dcache_valid
); /* On the valid list */
172 return (dcache_value (db
, addr
));
175 /* Write the word at ADDR both in the data cache and in the remote machine. */
177 dcache_poke (addr
, data
)
181 register struct dcache_block
*db
;
183 /* First make sure the word is IN the cache. DB is its cache block. */
184 db
= dcache_hit (addr
);
187 db
= dcache_alloc ();
189 hms_write_inferior_memory(addr
& ~LINE_SIZE_MASK
, (unsigned char *)db
->data
, LINE_SIZE
);
191 db
->addr
= addr
& ~LINE_SIZE_MASK
;
192 remque (db
); /* Off the free list */
193 insque (db
, &dcache_valid
); /* On the valid list */
196 /* Modify the word in the cache. */
197 db
->data
[XFORM(addr
)] = data
;
199 /* Send the changed word. */
201 hms_write_inferior_memory(addr
, (unsigned char *)&data
, 4);
205 /* The cache itself. */
206 struct dcache_block the_cache
[DCACHE_SIZE
];
208 /* Initialize the data cache. */
213 register struct dcache_block
*db
;
216 dcache_free
.next
= dcache_free
.last
= &dcache_free
;
217 dcache_valid
.next
= dcache_valid
.last
= &dcache_valid
;
218 for (i
=0;i
<DCACHE_SIZE
;i
++,db
++)
219 insque (db
, &dcache_free
);
223 /***********************************************************************
224 * I/O stuff stolen from remote-eb.c
225 ***********************************************************************/
227 static int timeout
= 2;
229 static const char *dev_name
;
232 /* Descriptor for I/O to remote machine. Initialize it to -1 so that
233 hms_open knows that we don't have a file open when the program
242 error("remote device not open");
249 /* Read a character from the remote system, doing all the fancy
255 buf
= serial_readchar(timeout
);
258 error ("Timeout reading from remote system.");
270 buf
= serial_readchar(timeout
);
271 if (buf
< 0) buf
= 0;
279 /* Keep discarding input from the remote system, until STRING is found.
280 Let the user break out immediately. */
291 if (readchar() == *p
)
305 /* Keep discarding input until we see the hms prompt.
307 The convention for dealing with the prompt is that you
309 o *then* wait for the prompt.
311 Thus the last thing that a procedure does with the serial line
312 will be an expect_prompt(). Exception: hms_resume does not
313 wait for the prompt, because the terminal is being handed over
314 to the inferior. However, the next thing which happens after that
315 is a hms_wait which does wait for the prompt.
316 Note that this includes abnormal exit, e.g. error(). This is
317 necessary to prevent getting into states from which we can't
325 /* Get a hex digit from the remote system & return its value.
326 If ignore_space is nonzero, ignore spaces (not newline, tab, etc). */
328 get_hex_digit (ignore_space
)
335 if (ch
>= '0' && ch
<= '9')
337 else if (ch
>= 'A' && ch
<= 'F')
338 return ch
- 'A' + 10;
339 else if (ch
>= 'a' && ch
<= 'f')
340 return ch
- 'a' + 10;
341 else if (ch
== ' ' && ignore_space
)
346 error ("Invalid hex digit from remote system.");
351 /* Get a byte from hms_desc and put it in *BYT. Accept any number
359 val
= get_hex_digit (1) << 4;
360 val
|= get_hex_digit (0);
364 /* Read a 32-bit hex word from the hms, preceded by a space */
372 for (j
= 0; j
< 8; j
++)
373 val
= (val
<< 4) + get_hex_digit (j
== 0);
376 /* Called when SIGALRM signal sent due to alarm() timeout. */
380 /* Number of SIGTRAPs we need to simulate. That is, the next
381 NEED_ARTIFICIAL_TRAP calls to hms_wait should just return
382 SIGTRAP without actually waiting for anything. */
384 static int need_artificial_trap
= 0;
387 hms_kill(arg
,from_tty
)
397 * Download a file specified in 'args', to the hms.
400 hms_load(args
,fromtty
)
413 abfd
= bfd_openr(args
,"coff-h8300");
416 printf_filtered("Unable to open file %s\n", args
);
420 if (bfd_check_format(abfd
, bfd_object
) ==0)
422 printf_filtered("File is not an object file\n");
427 while (s
!= (asection
*)NULL
)
429 if (s
->flags
& SEC_LOAD
)
435 char *buffer
= xmalloc(DELTA
);
436 printf_filtered("%s\t: 0x%4x .. 0x%4x ",s
->name
, s
->vma
, s
->vma
+ s
->_raw_size
);
437 for (i
= 0; i
< s
->_raw_size
; i
+= DELTA
)
440 if (delta
> s
->_raw_size
- i
)
441 delta
= s
->_raw_size
- i
;
443 bfd_get_section_contents(abfd
, s
, buffer
, i
, delta
);
444 hms_write_inferior_memory(s
->vma
+ i
, buffer
, delta
);
445 printf_filtered("*");
448 printf_filtered( "\n");
453 sprintf(buffer
, "r PC=%x", abfd
->start_address
);
454 hms_write_cr(buffer
);
458 /* This is called not only when we first attach, but also when the
459 user types "run" after having attached. */
461 hms_create_inferior (execfile
, args
, env
)
470 error ("Can't pass arguments to remote hms process.");
472 if (execfile
== 0 || exec_bfd
== 0)
473 error ("No exec file specified");
475 entry_pt
= (int) bfd_get_start_address (exec_bfd
);
480 hms_clear_breakpoints();
481 init_wait_for_inferior ();
485 insert_breakpoints (); /* Needed to get correct instruction in cache */
486 proceed(entry_pt
, -1, 0);
490 /* Open a connection to a remote debugger.
491 NAME is the filename used for communication, then a space,
499 while (*s
&& !isspace(*s
))
504 static char *get_word(p
)
519 while (*s
&& !isspace(*s
))
525 copy
= xmalloc(len
+1);
526 memcpy(copy
, word
, len
);
532 static int baudrate
= 9600;
538 /* Put this port into NORMAL mode, send the 'normal' character */
540 hms_write("\001", 1); /* Control A */
541 hms_write("\r", 1); /* Cr */
545 ok
= serial_readchar(timeout
);
551 if (readchar_nofail() == 'r')
554 /* Not the right baudrate, or the board's not on */
560 if (!serial_setbaudrate(baudrate
))
561 error("Can't set baudrate");
567 while (!is_baudrate_right())
569 baudrate
= serial_nextbaudrate(baudrate
);
571 printf_filtered("Board not yet in sync\n");
574 printf_filtered("Board not responding, trying %d baud\n",baudrate
);
576 serial_setbaudrate(baudrate
);
581 hms_open (name
, from_tty
)
595 if (name
&& strlen(name
))
596 dev_name
= strdup(name
);
597 if (!serial_open(dev_name
))
598 perror_with_name ((char *)dev_name
);
604 get_baudrate_right();
606 /* Hello? Are you there? */
607 serial_write("\r",1);
610 /* Clear any break points */
611 hms_clear_breakpoints();
613 printf_filtered("Connected to remote H8/300 HMS system.\n");
616 /* Close out all files and local state before this target loses control. */
624 /* Clear any break points */
625 hms_clear_breakpoints();
627 /* Put this port back into REMOTE mode */
628 sleep(1); /* Let any output make it all the way back */
629 serial_write("R\r", 2);
634 /* Terminate the open connection to the remote debugger.
635 Use this when you want to detach and do something else
638 hms_detach (args
,from_tty
)
644 hms_clear_breakpoints();
647 pop_target(); /* calls hms_close to do the real work */
649 printf_filtered ("Ending remote %s debugging\n", target_shortname
);
652 /* Tell the remote machine to resume. */
655 hms_resume (step
, sig
)
665 /* Force the next hms_wait to return a trap. Not doing anything
666 about I/O from the target means that the user has to type
667 "continue" to see any. FIXME, this should be fixed. */
668 need_artificial_trap
= 1;
677 /* Wait until the remote machine stops, then return,
678 storing status in STATUS just as `wait' would. */
684 /* Strings to look for. '?' means match any single character.
685 Note that with the algorithm we use, the initial character
686 of the string cannot recur in the string, or we will not
687 find some cases of the string in the input. */
689 static char bpt
[] = "At breakpoint:";
690 /* It would be tempting to look for "\n[__exit + 0x8]\n"
691 but that requires loading symbols with "yc i" and even if
692 we did do that we don't know that the file has symbols. */
693 static char exitmsg
[] = "HMS>";
697 /* Large enough for either sizeof (bpt) or sizeof (exitmsg) chars. */
699 /* Current position in swallowed. */
700 char *swallowed_p
= swallowed
;
704 int old_timeout
= timeout
;
705 int old_immediate_quit
= immediate_quit
;
706 int swallowed_cr
= 0;
708 WSETEXIT ((*status
), 0);
710 if (need_artificial_trap
!= 0)
712 WSETSTOP ((*status
), SIGTRAP
);
713 need_artificial_trap
--;
717 timeout
= 99999; /* Don't time out -- user program is running. */
718 immediate_quit
= 1; /* Helps ability to QUIT */
721 QUIT
; /* Let user quit and leave process running */
737 if (ch
== *ep
|| *ep
== '?')
754 /* Print out any characters which have been swallowed. */
755 for (p
= swallowed
; p
< swallowed_p
; ++p
)
757 swallowed_p
= swallowed
;
760 if ((ch
!= '\r' && ch
!= '\n') || swallowed_cr
>10)
771 WSETSTOP ((*status
), SIGTRAP
);
776 WSETEXIT ((*status
), 0);
779 timeout
= old_timeout
;
780 immediate_quit
= old_immediate_quit
;
784 /* Return the name of register number REGNO
785 in the form input and output by hms.
787 Returns a pointer to a static buffer containing the answer. */
792 static char *rn
[NUM_REGS
]= REGISTER_NAMES
;
796 /* Read the remote registers. */
797 static int gethex(length
, start
, ok
)
806 if (*start
>='a' && *start
<= 'f')
808 result
+= *start
- 'a' + 10;
810 else if (*start
>='A' && *start
<= 'F')
812 result
+= *start
- 'A' + 10;
814 else if (*start
>='0' && *start
<= '9')
816 result
+= *start
- '0' ;
825 timed_read(buf
, n
, timeout
)
836 if (c
== 0) return i
;
851 for (i
= 0; i
< l
; i
++)
860 hms_write( s
, strlen(s
));
865 hms_fetch_register (dummy
)
868 #define REGREPLY_SIZE 79
869 char linebuf
[REGREPLY_SIZE
+1];
874 REGISTER_TYPE reg
[NUM_REGS
];
882 s
= timed_read(linebuf
, REGREPLY_SIZE
, 1);
885 linebuf
[REGREPLY_SIZE
] = 0;
887 if (linebuf
[0] == 'r' &&
891 linebuf
[75] == 'H' &&
892 linebuf
[76] == 'M' &&
896 PC=XXXX CCR=XX:XXXXXXXX R0-R7= XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX
897 5436789012345678901234567890123456789012345678901234567890123456789012
902 reg
[PC_REGNUM
] = gethex(4,linebuf
+6, &gottok
);
903 reg
[CCR_REGNUM
] = gethex(2,linebuf
+15, &gottok
);
904 for (i
= 0; i
< 8; i
++)
906 reg
[i
] = gethex(4, linebuf
+34+5*i
, &gottok
);
911 for (i
= 0; i
< NUM_REGS
; i
++)
915 swapped
[0] = (reg
[i
])>> 8;
917 supply_register (i
, swapped
);
922 /* Store register REGNO, or all if REGNO == -1.
923 Return errno value. */
925 hms_store_register (regno
)
929 /* printf("hms_store_register() called.\n"); fflush(stdout); /* */
932 for (regno
= 0; regno
< NUM_REGS
; regno
++)
934 hms_store_register(regno
);
939 char *name
= get_reg_name (regno
);
941 sprintf(buffer
,"r %s=%x", name
, read_register(regno
));
942 hms_write_cr(buffer
);
949 /* Get ready to modify the registers array. On machines which store
950 individual registers, this doesn't need to do anything. On machines
951 which store all the registers in one fell swoop, this makes sure
952 that registers contains all the registers from the program being
956 hms_prepare_to_store ()
958 /* Do nothing, since we can store individual regs */
970 /* Read a word from remote address ADDR and return it.
971 * This goes through the data cache.
974 hms_fetch_word (addr
)
977 return dcache_fetch (addr
);
980 /* Write a word WORD into remote address ADDR.
981 This goes through the data cache. */
984 hms_store_word (addr
, word
)
988 dcache_poke (addr
, word
);
992 hms_xfer_inferior_memory(memaddr
, myaddr
, len
, write
, target
)
997 struct target_ops
*target
; /* ignored */
1000 /* Round starting address down to longword boundary. */
1001 register CORE_ADDR addr
;
1002 /* Round ending address up; get number of longwords that makes. */
1004 /* Allocate buffer of that many longwords. */
1005 register int *buffer
;
1008 addr
= memaddr
& - sizeof (int);
1009 count
= (((memaddr
+ len
) - addr
) + sizeof (int) - 1) / sizeof (int);
1012 buffer
= (int *)alloca (count
* sizeof (int));
1015 /* Fill start and end extra bytes of buffer with existing memory data. */
1017 if (addr
!= memaddr
|| len
< (int)sizeof (int)) {
1018 /* Need part of initial word -- fetch it. */
1019 buffer
[0] = hms_fetch_word (addr
);
1022 if (count
> 1) /* FIXME, avoid if even boundary */
1025 = hms_fetch_word (addr
+ (count
- 1) * sizeof (int));
1028 /* Copy data to be written over corresponding part of buffer */
1030 bcopy (myaddr
, (char *) buffer
+ (memaddr
& (sizeof (int) - 1)), len
);
1032 /* Write the entire buffer. */
1034 for (i
= 0; i
< count
; i
++, addr
+= sizeof (int))
1037 hms_store_word (addr
, buffer
[i
]);
1048 /* Read all the longwords */
1049 for (i
= 0; i
< count
; i
++, addr
+= sizeof (int))
1052 buffer
[i
] = hms_fetch_word (addr
);
1060 /* Copy appropriate bytes out of the buffer. */
1061 bcopy ((char *) buffer
+ (memaddr
& (sizeof (int) - 1)), myaddr
, len
);
1069 hms_write_inferior_memory (memaddr
, myaddr
, len
)
1071 unsigned char *myaddr
;
1083 thisgo
= len
- done
;
1084 if (thisgo
> 20) thisgo
= 20;
1086 sprintf(buffer
,"M.B %4x =", memaddr
+done
);
1087 hms_write(buffer
,10);
1088 for (idx
= 0; idx
< thisgo
; idx
++)
1091 sprintf(buf
, "%2x ", myaddr
[idx
+done
]);
1105 char *file
= "nothing";
1107 file
= bfd_get_filename(exec_bfd
);
1111 printf_filtered("\tAttached to DOS asynctsr and running program %s\n",file
);
1113 printf_filtered("\tAttached to %s at %d baud and running program %s\n",file
);
1115 printf_filtered("\ton an H8/300 processor.\n");
1118 /* Copy LEN bytes of data from debugger memory at MYADDR
1119 to inferior's memory at MEMADDR. Returns errno value.
1120 * sb/sh instructions don't work on unaligned addresses, when TU=1.
1124 /* Read LEN bytes from inferior memory at MEMADDR. Put the result
1125 at debugger address MYADDR. Returns errno value. */
1127 hms_read_inferior_memory(memaddr
, myaddr
, len
)
1132 /* Align to nearest low 16 bits */
1136 CORE_ADDR start
= memaddr
& ~0xf;
1137 CORE_ADDR end
= ((memaddr
+ len
+16) & ~0xf) -1;
1139 CORE_ADDR start
= memaddr
;
1140 CORE_ADDR end
= memaddr
+ len
-1;
1145 AAAA: XXXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX '................'
1146 012345678901234567890123456789012345678901234567890123456789012345
1150 if (memaddr
& 0xf) abort();
1151 if (len
!= 16) abort();
1153 sprintf(buffer
, "m %4x %4x", start
& 0xffff, end
& 0xffff);
1154 hms_write_cr(buffer
);
1155 /* drop the echo and newline*/
1156 for (i
= 0; i
< 13; i
++)
1161 /* Grab the lines as they come out and fill the area */
1171 buffer
[0] = readchar();
1172 if (buffer
[0] == 'M')
1174 for (i
= 1; i
< 66; i
++)
1175 buffer
[i
] = readchar();
1177 /* Now parse the line */
1179 addr
= gethex(4, buffer
, &ok
);
1181 for (p
= 0; p
< 16; p
+=2)
1183 byte
[p
] = gethex(2, buffer
+ idx
, &ok
);
1184 byte
[p
+1] = gethex(2, buffer
+ idx
+ 2, &ok
);
1190 for (p
= 0; p
<16;p
++)
1192 if (addr
+ p
>= memaddr
&&
1193 addr
+ p
< memaddr
+ len
)
1195 myaddr
[ (addr
+ p
)-memaddr
] = byte
[p
];
1206 /* This routine is run as a hook, just before the main command loop is
1207 entered. If gdb is configured for the H8, but has not had its
1208 target specified yet, this will loop prompting the user to do so.
1211 hms_before_main_loop ()
1215 extern FILE *instream
;
1216 extern jmp_buf to_top_level
;
1218 push_target (&hms_ops
);
1222 #define MAX_BREAKS 16
1223 static int num_brkpts
=0;
1225 hms_insert_breakpoint(addr
, save
)
1227 char *save
; /* Throw away, let hms save instructions */
1231 if (num_brkpts
< MAX_BREAKS
)
1235 sprintf(buffer
,"b %x", addr
& 0xffff);
1236 hms_write_cr(buffer
);
1242 fprintf_filtered(stderr
,
1243 "Too many break points, break point not installed\n");
1250 hms_remove_breakpoint(addr
, save
)
1252 char *save
; /* Throw away, let hms save instructions */
1259 sprintf(buffer
,"b - %x", addr
& 0xffff);
1260 hms_write_cr(buffer
);
1267 /* Clear the hmss notion of what the break points are */
1269 hms_clear_breakpoints()
1273 hms_write_cr("b -");
1281 hms_clear_breakpoints();
1282 generic_mourn_inferior ();
1287 /* Put a command string, in args, out to the hms. The hms is assumed to
1288 be in raw mode, all writing/reading done through desc.
1289 Ouput from the hms is placed on the users terminal until the
1290 prompt from the hms is seen.
1291 FIXME: Can't handle commands that take input. */
1294 hms_com (args
, fromtty
)
1302 /* Clear all input so only command relative output is displayed */
1305 hms_write("\030",1);
1309 /* Define the target subroutine names */
1311 struct target_ops hms_ops
= {
1312 "hms", "Remote HMS monitor",
1313 "Use the H8 evaluation board running the HMS monitor connected\n\
1316 hms_open
, hms_close
,
1317 0, hms_detach
, hms_resume
, hms_wait
, /* attach */
1318 hms_fetch_register
, hms_store_register
,
1319 hms_prepare_to_store
,
1320 hms_xfer_inferior_memory
,
1322 hms_insert_breakpoint
, hms_remove_breakpoint
, /* Breakpoints */
1323 0, 0, 0, 0, 0, /* Terminal handling */
1324 hms_kill
, /* FIXME, kill */
1326 0, /* lookup_symbol */
1327 hms_create_inferior
, /* create_inferior */
1328 hms_mourn
, /* mourn_inferior FIXME */
1330 0, /* notice_signals */
1331 process_stratum
, 0, /* next */
1332 1, 1, 1, 1, 1, /* all mem, mem, stack, regs, exec */
1333 0,0, /* Section pointers */
1334 OPS_MAGIC
, /* Always the last thing */
1342 printf_filtered("Snoop disabled\n");
1344 printf_filtered("Snoop enabled\n");
1353 dev_name
= get_word(&s
);
1367 int newrate
= atoi(s
);
1369 if (!serial_setbaudrate(newrate
))
1370 error("Can't use %d baud\n", newrate
);
1372 printf_filtered("Checking target is in sync\n");
1374 get_baudrate_right();
1376 printf_filtered("Sending commands to set target to %d\n",
1379 sprintf(buffer
, "tm %d. N 8 1", baudrate
);
1380 hms_write_cr(buffer
);
1384 /***********************************************************************/
1387 _initialize_remote_hms ()
1389 add_target (&hms_ops
);
1390 add_com ("hms <command>", class_obscure
, hms_com
,
1391 "Send a command to the HMS monitor.");
1392 add_com ("snoop", class_obscure
, hms_quiet
,
1393 "Show what commands are going to the monitor");
1395 add_com ("device", class_obscure
, hms_device
,
1396 "Set the terminal line for HMS communications");
1398 add_com ("speed", class_obscure
, hms_speed
,
1399 "Set the terminal line speed for HMS communications");
1401 dev_name
= serial_default_name();
This page took 0.057028 seconds and 4 git commands to generate.