zoukankan      html  css  js  c++  java
  • Embedding with GNU: the gdb Remote Serial Protocol

     

     

     

     

     

     

    In September, I introduced the
    topic  of  the  GNU  debugger,
    gdb. 1 I   discussed   how   its
    remote   debugging   feature
    could be used to debug code
    running  in  an  embedded  sys-
    tem  connected  to  a  PC  by  a  serial
    cable,  network  connection,  or  some
    other means. While commercial prod-
    ucts with this capability are also avail-
    able, in my opinion the freely available
    gdb is the preferred solution because
    it  provides  portable,  sophisticated
    debugging  over  a  broad  range  of
    embedded  systems,  including  devices
    with  communications  interfaces  or
    resource constraints too restrictive for
    general commercial support.
    I  also  mentioned  in  that  article
    that, to make remote debugging possi-
    ble,  gdb  requires  the  services  of  a
    debugging  stub—a  small  library  of
    code  in  the  debugging  target  that
    manages    registers    and    memory,
    responds  to  breakpoints,  and  reports
    application status to gdb via the com-
    munications  link.  That  article  con-
    tained excerpts from a debugging stub
    for  the  Hitachi  SH-2  microcontroller,
    but I didn’t actually put enough of the
    pieces  together  to  show  how  a  com-
    plete debugging stub would work.
    I’ll  fix  that  this  month  by  present-
    ing  in  detail  the  GDB  Remote  Serial
    Protocol—gdb’s    standard    remote
    communications  protocol.  Once  you
    are comfortable with how your proces-
    sor  handles  breakpoint  and  other
    108  NOVEMBER 1999  Embedded Systems Programming
    B I L L   G A T L I F F
    f  e  a  t  u  r  e
    Embedding
    with GNU: the
    gdb Remote
    Serial Protocol
    In this installment of a series on GNU-based embedded development, the
    author wraps up his discussion of using the GNU debugger, gdb, to debug
    embedded applications remotely.
    I
    Embedded Systems Programming  NOVEMBER 1999   109
    exceptions,  then  knowledge  of  a  few
    basic Remote Serial Protocol messages
    is all you need to get your embedded
    system talking to gdb.
    The protocol defined
    The  GDB  Remote  Serial  Protocol
    (RSP)  is  a  simple,  ASCII  message-
    based protocol suitable for use on ser-
    ial  lines,  local  area  networks,  or  just
    about   any   other   communications
    medium that can support at least half-
    duplex data exchange.
    RSP  packets  begin  with  a  dollar
    sign  ($),  followed  by  one  or  more
    ASCII bytes that make up the message
    being sent, and end with a pound sign
    (#) and two ASCII hex characters rep-
    resenting  the  message’s  checksum.
    For  example,  the  following  is  a  com-
    plete RSP packet:
    $m4015bc,2#5a
    The    receiver    of    the    packet
    responds immediately with either a “+”
    or  a  “-”  to  indicate  that  the  message
    was received either intact or in error,
    respectively.
    A  typical  transaction  involves  gdb
    issuing a command to a debugging tar-
    get, which then responds with data, a
    simple acknowledgement, or a target-
    specific  error  code.  If  the  latter  is
    returned, gdb will report the code to
    the  user  and  halt  whatever  activity  is
    currently in progress.
    The  console    output  message,
    which  debugging  targets  use  to  print
    text  on  the  gdb  console,  is  the  lone
    exception  to  the  typical  command-
    response   sequence.   Except   when
    another   command   is   already   in
    progress,  this  message  can  be  sent
    from the debugging stub to gdb at any
    time.
    The following paragraphs describe
    the RSP’s essential commands. For the
    purposes of this tutorial, I have divid-
    ed the messages into three categories:
    register-  and  memory-related  com-
    mands,  program  control  commands,
    and other commands.
    Register- and memory-
    related commands
    Here are the commands to read from
    and write to registers.
    Read registers (“g”)
    Example: $g#67
    The  debugger  will  issue  this  com-
    mand  whenever  it  needs  to  know
    everything  about  the  debugging  tar-
    get’s  current  register  state.  An  exam-
    ple target response would be:
    + $123456789abcdef0...#xx
    (Register 0 is 0x12345678, register 1 is
    0x9abcdef0, and so on.)
    The response is an ordered stream
    of  bytes  representing  register  data
    ordered per the definition in the tar-
    get’s  macro  file,  gdb/config/<arch>/
    tm-<arch>.h  (for  example,  gdb/con-
    fig/sh/tm-sh.h for the Hitachi SH).
    Write registers (“G”)
    Example: $G123456789abcdef0...#xx
    (Set register 0 to 0x12345678, register
    1 to 0x9abcdef0, and so on.)
    This message is the complement to
    the  read  registers command.  With
    this   command,   gdb   supplies   an
    ordered  stream  of  bytes  representing
    data to be stored in the target proces-
    sor’s registers immediately before pro-
    gram execution resumes. An example
    target response:
    + $OK#9a
    Write register N (“P”)
    Example: $P10=0040149c#b3
    (Set register 16 to the value 0x40149c.)
    When  it  wants  to  set  the  value  of
    only  one  or  two  registers,  gdb  sends
    this  command  instead  of  sending  a
    complete register set to the debugging
    target. The register numbering is the
    same as that used in the read regis-
    ters and write registers commands.
    An example target response:
    + $OK#9a
    Below  are  the  commands  to  read
    from and write to memory.
    Read memory (“m”)
    Example: $m4015bc,2#5a
    (Read  two  bytes,  starting  at  address
    0x4015bc.)
    A read memory command is sent by
    gdb  to  determine  the  values  of  local
    and  global  variables,  the  value  of  an
    opcode  about  to  be  replaced  by  a
    breakpoint instruction, and any other
    kind of information the user requests.
    The  debugger  generally  is  aware  of
    any   endian   issues   present   in   the
    debugging  target,  so  the  target  need
    only  return  the  result  as  a  simple
    stream  of  bytes;  gdb  will  reformat
    them as appropriate.
    Debugging stubs on targets that are
    sensitive  to  data  widths  should  opti-
    mize the implementation of the write
    memory and read memory commands as
    the  target  architecture  dictates.  For
    example,  certain  peripheral  configu-
    ration  registers  in  the  Hitachi  SH-2
    processor family can only be properly
    read  and  written  in  16-bit  or  32-bit
    units, so a debugging stub for this tar-
    get should use 16-bit or 32-bit accesses
    whenever possible. An example target
    response:
    + $2f86#06
    Write memory (“M”)
    Example: M4015cc,2:c320#6d
    In my opinion the freely available gdb is the preferred solution
    because it provides portable, sophisticated debugging over a broad
    range of embedded systems.
    C O R B I S / T O M   B R A K E F I E L D
    gdb rsp
    (Write  the  value  0xc320  to  address
    0x4015cc.)
    This command is the complement
    to  the  read   memory command.  An
    example target response:
    + $OK#9a
    Program control commands
    Program  control  commands  are  mes-
    sages  that  gdb  uses  to  control  the
    behavior  of  the  application  being
    debugged.  As  such,  these  commands
    are  somewhat  more  complicated  to
    implement than the more basic regis-
    ter-  and  memory-related  commands
    we’ve already covered.
    Get last signal (“?”)
    Example: $?#3f
    This  command  is  used  to  find  out
    how the target reached its current state.
    The  response  is  the  same  as  the  “Last
    signal” response documented below.
    Step (“s”)
    Example: $s#73
    When it wants the target to execute
    exactly one assembly language instruc-
    tion,  gdb  issues  a  step command  to
    the  debugging  target.  The  debugger
    sends  this  command  when  the  user
    types stepior stepat the gdb console.
    An  example  target  response  follows
    the continue command description.
    Continue (“c”)
    Example: $c#63
    A  continue  command  is  issued
    when  gdb  releases  the  application  to
    run at full speed, as happens when the
    user  enters  a  continue command  at
    the  gdb  console.  An  example  target
    response follows.
    Responses  to  the  step  and  continue  com-
    mands.  A  debugging  stub  does  not
    immediately  respond  to  the  step or
    continue  commands,  other  than  to
    send  the  “+”  that  signifies  proper
    reception  of  the  packet.  Instead,  the
    stub  provides  a  response  when  the
    next   breakpoint   is   reached,   the
    requested  instruction  has  been  exe-
    cuted  (in  the  case  of  the  step com-
    mand),  an  exception  occurs,  or  the
    application exits.
    There  are  two  ways  to  respond  to
    these  commands:  a  brief  “last  signal”
    response, or a more useful “expedited
    response.”
    “Last signal” response (“S”)
    Example: $S05#b8
    This  is  the  minimum  reply  to  the
    last signal, step, and continue com-
    mands. The “05” in the response can
    be any one of the signal values used in
    the  standard  POSIX  signal()  func-
    tion call. For example, “5” is a break-
    point  exception,  “10”  is  a  bus  error,
    and so forth.
    Expedited response (“T”)
    Example: $T0510:1238;F:FFE0...#xx
    This  message  combines  the  infor-
    mation in a last signalresponse (the
    “05” in the example message) with key
    register values that gdb may be imme-
    diately  interested  in.  Designed  to
    improve  gdb’s  performance  during
    code stepping, this message allows gdb
    to  avoid  a  read  registers request  if
    the  values  it  needs  (the  target’s  pro-
    gram counter and status register, gen-
    erally) are included in this message.
    Registers are identified by the same
    numbering  scheme  used  in  the  read
    registers and write registers com-
    mands;  in  the  example  provided,  the
    value of register 16 (10 hex) is 0x1238,
    and register 15 (F hex) contains 0xffe0.
    Other commands
    Console output (“O”)—optional
    Example:
    $O48656c6c6f2c20776f726c64210a#55
    (Prints  “Hello,  world!\n”  on  the  gdb
    console)
    110  NOVEMBER 1999  Embedded Systems Programming
    gdb rsp
    This command allows a debugging
    stub to send a text message to the gdb
    console.  The  text  to  be  displayed  is
    sent in its hex byte equivalent (‘H’ ==
    0x48)  and  gdb  will  queue  successive
    messages  until  it  sees  a  newline  (‘\n’,
    0x0a) character.
    This  message  always  originates  in
    the debugging target; gdb never sends
    a  console    output  message  to  the
    debugging target.
    Empty response (“”)
    If a debugging stub encounters a com-
    mand  it  doesn’t  support  or  under-
    stand,  it  should  return  an  empty
    response. This allows gdb to select an
    alternate command if one is available.
    Example: <an unrecognized command>
    Target response: + $#00
    Error response (“E”)
    When a debugging stub encounters an
    error  during  command  processing,  it
    should send an error response back to
    gdb. Bus errors and/or illegal address-
    es  during  memory  operations  are
    examples  of  commands  which  may
    generate  an  error  response  from  a
    debugging stub.
    Example: <a command that produces
    an error>
    Target reponse: +$E01#xx
    There  aren’t  any  predefined  error
    codes  in  gdb;  when  gdb  receives  an
    error message, it prints it on the con-
    sole   and   halts   the   operation   in
    progress.
    Putting it all together
    At this point, I’ve covered individually
    all  the  pieces  necessary  to  get  an
    embedded  system  talking  to  gdb.  In
    the last article, I covered traps, single-
    stepping, and a few gdb features; and
    in  the  previous  section  I  covered  the
    communications  protocol  that  gdb
    expects  a  debugging  stub  to  use.  All
    we have left to do now is to throw all of
    these pieces together, right?
    Actually,  we  must  deal  with  one
    more   minor   consideration   before
    we’re  really  ready  to  start  debugging
    code: the chicken-and-egg problem of
    actually  getting  the  debugging  stub
    into the embedded system for the first
    time,  so  that  gdb  has  something  with
    which to communicate when we turn
    on the power.
    Several  methods  of  attacking  this
    problem  exist. 2 To  me,  the  best  way
    always seems to be to place a minimal
    stub  into  some  kind  of  nonvolatile
    memory  in  the  target,  and  use  that
    code to both boot the system and help
    gdb download the rest of the applica-
    tion  into  RAM.  Once  gdb  starts  the
    application,  debugging  control  then
    transfers  to  a  second  debugging  stub
    linked with the application itself.
    Embedded Systems Programming  NOVEMBER 1999   111
    gdb rsp
    The   biggest   advantage   of   this
    approach  is  that  it  allows  you  to  con-
    tinue   developing   the   application-
    linked  debugging  stub  without  need-
    ing to reprogram the resident stub in
    the   target’s   nonvolatile   memory,
    which is a real bonus if the only non-
    volatile memory available is one-time-
    programmable  ROM.  Furthermore,
    because  the  resident  stub  needs  to
    know  only  the  simplest  commands—
    read   memory,  write   memory,  write
    register N, and continue—the likeli-
    hood of a serious bug being present in
    this code is fairly low.
    Another  approach  is  to  place  a
    complete debugging stub into the tar-
    get’s  nonvolatile  memory,  and  use  it
    for all debugging activities. This elimi-
    nates  the  need  to  link  a  debugging
    stub  with  the  target  application,  but
    may make it more difficult to change
    the stub if errors are found or new fea-
    tures are added.
    If you’re using a commercial micro-
    processor evaluation board, you might
    not need to provide a debugging stub
    at  all—gdb  may  already  support  the
    vendor’s protocol, or you may be able
    to add support to gdb after spending a
    few  minutes  reverse-engineering  the
    protocol  with  a  serial-port  analyzer.
    Check the vendor’s license agreement
    if  you  take  this  approach:  you  may
    need  to  sign  a  non-disclosure  agree-
    ment first, and you will definitely need
    to  seek  permission  before  releasing
    your  gdb  improvements  to  the  com-
    munity at large.
    Testing a debugging stub
    Once you think you have a debugging
    stub ready to go, you’ll want to test it
    as   thoroughly   as   possible   before
    putting  it  to  work.  Remember,  the
    only thing worse than a buggy applica-
    tion is a buggy development tool.
    The following is a test procedure I
    recommend  you  use  whenever  you
    make changes to your debugging stub,
    to  make  sure  things  are  working  the
    way they should.
    First, for convenience, add the fol-
    lowing lines to your .gdbinit file:
    set remotedebug 1
    set remotelogfile gdb_logfile
    These commands make gdb display all
    RSP messages exchanged between the
    host and the target, as well as log them
    to the file gdb_logfile.
    Next,  connect  gdb  to  the  remote
    target,  and  enter  the  target  remote
    [port] command.  As  gdb  makes  the
    connection,    watch    the    messages
    exchanged to make sure that your stub
    provides the proper responses to gdb’s
    requests.
    During  startup,  your  debugging
    stub  should  load  values  into  each  of
    the  target  processor’s  registers.  Use
    gdb’s  info   registers command  to
    confirm that gdb can properly receive
    and display these values.
    Next,  use  gdb’s  set command  to
    change a few register values, and make
    sure  that  the  stub  both  properly
    responds  to  gdb’s  write    register
    command,  and  returns  the  correct
    results in subsequent read registers
    commands  initiated  when  you  type
    info registers.
    Next,  do  the  same  thing  for  a  few
    memory  locations—have  the  stub  set
    the locations at startup, and then veri-
    fy  that  gdb  can  read  and  write  these
    locations on request. For example, try
    the following:
    print *(long*)0x1234
    set *(long*)0x1234=5678
    print *(long*)0x1234
    If  everything  works  so  far,  you’re
    ready to try out gdb’s load command.
    The console will get extremely noisy as
    gdb  displays  the  multitude  of  write
    memory commands it uses to transfer a
    test  application  to  the  target.  You’ll
    want  to  refer  to  the  log  file  then,  to
    ensure  that  everything  happened  as
    expected.  Once  this  has  been  com-
    pleted, check a few memory locations
    in the application’s code space to con-
    firm  that  the  expected  values  are
    there.
    The test application should contain
    some gdb console output if your stub
    112  NOVEMBER 1999  Embedded Systems Programming
    gdb rsp
    supports  this  command.  Enter  con-
    tinue at the gdb console, and see that
    the output appears as you expected.
    Reset the target, and reload the test
    application. Set a breakpoint immedi-
    ately before the line that performs the
    console output. Enter continue again,
    and  verify  both  that  the  application
    stops  where  it’s  supposed  to  and  that
    the  console  output  appears  properly
    when execution resumes.
    Next  (and  this  can  be  combined
    with the above test), reload the appli-
    cation,  set  a  breakpoint,  and  step
    through  a  few  source  lines  with  the
    step and stepi commands. Make sure
    that  local  variables  (viewed  with  the
    display command) change as expect-
    ed, and that they don’t change unex-
    pectedly,  particularly  when  stepping
    through opcodes that branch or jump.
    Also,  monitor  the  program  counter,
    stack  pointer,  and  other  register  val-
    ues, to make sure they change as your
    code dictates they should.
    At this point, your stub is ready to
    go.
    Final thoughts
    In  my  opinion,  gdb  has  no  equal  in
    the  debugging  tool  community,  free
    or otherwise. In addition to its stability
    and  long  list  of  useful  features,  gdb
    provides  the  flexibility  that  today’s
    embedded developers need at a price
    that’s hard to beat. For those willing to
    invest the time necessary to develop a
    debugging stub, the rewards are both
    a  thorough  understanding  of  their
    embedded  target’s  architecture,  and
    the  services  of  a  powerful,  extensible
    debugger. esp
    Bill Gatliff is a freelance embedded develop-
    er   and   senior   design   engineer   with
    Komatsu  Mining  Systems,  Inc.  in  Peoria,
    IL,  and  is  a  semi-regular  presenter  at  the
    Embedded Systems Conferences. He can be
    reached at bgat@usa.net.
    References
    1. Gatliff, Bill, “Embedding with GNU:
    GNU Debugger,” Embedded Systems
    Programming, September 1999, p. 80.
    2 Actually, there are no fewer than seven
    different ways of accomplishing this,
    depending on which services the target
    can provide itself vs. which services it
    needs external help with. For a more
    thorough presentation on this subject,
    see the 1999 Embedded Systems
    Conference Proceedings for a paper
    entitled “gdb: An Open Source
    Debugger for Embedded Development,”
    by Stan Shebs, PhD, of Cygnus
    Solutions.
    Embedded Systems Programming  NOVEMBER 1999   113

    作者:linucos

    出处:http://linucos.cnblogs.com

    声明因文章引起的任何问题,本博客不负任何责任;版权所有,欢迎转载 
  • 相关阅读:
    Application package 'AndroidManifest.xml' must have a minimum of 2 segments.
    让“是男人就下到100层”在Android平台上跑起来
    移植一个cocos2d-x游戏
    cocos2d-x宏定义
    职场之需求
    cocos2d-x for android配置 & 运行 Sample on Linux OS
    input函数出现的问题(Python)
    职场之英语
    职场之随手记
    应用商店后台MIS的一些思考
  • 原文地址:https://www.cnblogs.com/linucos/p/2939162.html
Copyright © 2011-2022 走看看