source: trunk/libs/newlib/src/libgloss/xstormy16/xstormy16_stub.c @ 444

Last change on this file since 444 was 444, checked in by satin@…, 6 years ago

add newlib,libalmos-mkh, restructure shared_syscalls.h and mini-libc

File size: 19.2 KB
Line 
1/****************************************************************************
2
3                THIS SOFTWARE IS NOT COPYRIGHTED
4
5   HP offers the following for use in the public domain.  HP makes no
6   warranty with regard to the software or it's performance and the
7   user accepts the software "AS IS" with all faults.
8
9   HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD
10   TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES
11   OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
12
13****************************************************************************/
14
15/****************************************************************************
16 *  Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $
17 *
18 *  Module name: remcom.c $
19 *  Revision: 1.34 $
20 *  Date: 91/03/09 12:29:49 $
21 *  Contributor:     Lake Stevens Instrument Division$
22 *
23 *  Description:     low level support for gdb debugger. $
24 *
25 *  Considerations:  only works on target hardware $
26 *
27 *  Written by:      Glenn Engel $
28 *  ModuleState:     Experimental $
29 *
30 *  NOTES:           See Below $
31 *
32 *  Heavily modified for XStormy16 by Mark Salter, Red Hat.
33 *  Optimisations and 'X' support by Geoff Keating, Red Hat.
34 *
35 *  To enable debugger support, two things need to happen.  One, a
36 *  call to set_debug_traps() is necessary in order to allow any breakpoints
37 *  or error conditions to be properly intercepted and reported to gdb.
38 *  Two, a breakpoint needs to be generated to begin communication.  This
39 *  is most easily accomplished by a call to breakpoint().  Breakpoint()
40 *  simulates a breakpoint by executing a trap #1.
41 *
42 *  Because gdb will sometimes write to the stack area to execute function
43 *  calls, this program cannot rely on using the inferior stack so it uses
44 *  it's own stack area.
45 *
46 *************
47 *
48 *    The following gdb commands are supported:
49 *
50 * command          function                               Return value
51 *
52 *    g             return the value of the CPU registers  hex data or ENN
53 *    G             set the value of the CPU registers     OK or ENN
54 *
55 *    mAA..AA,LLLL  Read LLLL bytes at address AA..AA      hex data or ENN
56 *    MAA..AA,LLLL: Write LLLL bytes at address AA.AA      OK or ENN
57 *    XAA..AA,LLLL: Write LLLL binary bytes at address     OK or ENN
58 *                  AA..AA
59 *
60 *    c             Resume at current address              SNN   ( signal NN)
61 *    cAA..AA       Continue at address AA..AA             SNN
62 *
63 *    s             Step one instruction                   SNN
64 *    sAA..AA       Step one instruction from AA..AA       SNN
65 *
66 *    k             kill
67 *
68 *    ?             What was the last sigval ?             SNN   (signal NN)
69 *
70 * All commands and responses are sent with a packet which includes a
71 * checksum.  A packet consists of
72 *
73 * $<packet info>#<checksum>.
74 *
75 * where
76 * <packet info> :: <characters representing the command or response>
77 * <checksum>    :: <two hex digits computed as modulo 256 sum of <packetinfo>>
78 *
79 * When a packet is received, it is first acknowledged with either '+' or '-'.
80 * '+' indicates a successful transfer.  '-' indicates a failed transfer.
81 *
82 * Example:
83 *
84 * Host:                  Reply:
85 * $m0,10#2a               +$00010203040506070809101112131415#42
86 *
87 ****************************************************************************/
88
89/* Local functions:
90 */
91static void putDebugChar(unsigned ch);
92static unsigned char getDebugChar(void);
93static void putPacket(unsigned char *);
94static void putHex (char c, unsigned long mem_arg, int count);
95static unsigned char *getpacket(void);
96static void hex2mem(unsigned char *, unsigned long, int);
97static int valid_addr_range (unsigned long mem, int count);
98static int  hexToInt(unsigned char **, long *);
99static void prepare_to_step(void);
100static void finish_from_step(void);
101
102/* breakpoint opcode */
103#define BREAKPOINT_OPCODE 0x0006
104
105/* Error Detection Register */
106#define ERR_DETECT_REG  (*(volatile unsigned *)0x7f08)
107#define UNDEF_INSN_ENA   0x01
108#define UNDEF_INSN_FLAG  0x02
109#define ODD_ADDR_ENA     0x04
110#define ODD_ADDR_FLAG    0x08
111#define BAD_ADDR_ENA     0x10
112#define BAD_ADDR_FLAG    0x20
113#define SER0_IRQ_ENA     0x1000
114#define SER0_IRQ_FLAG    0x2000
115
116/*****************************************************************************
117 * BUFMAX defines the maximum number of characters in inbound/outbound buffers
118 * at least NUMREGBYTES*2 are needed for register packets
119 */
120#define BUFMAX 80
121
122static const unsigned char hexchars[]="0123456789abcdef";
123
124#define NUMREGS 17
125
126/* Number of bytes of registers (extra 2 bytes is for 4 byte PC).  */
127#define NUMREGBYTES ((NUMREGS * 2) + 2)
128enum regnames { R0,  R1,  R2,  R3,  R4,  R5,  R6,   R7,
129                R8,  R9,  R10, R11, R12, R13, R14,  R15,
130                PC };
131
132#define FP  R13
133#define PSW R14
134#define SP  R15
135
136struct regs {
137    int  r[16];
138    long pc;
139} registers;
140
141static struct regs orig_registers;
142
143static unsigned char remcomBuffer[BUFMAX];
144
145/* Indicate whether inferior is running. Used to decide whether or not to
146   send T packet when stub is entered. */
147static char is_running;
148
149static inline unsigned char
150get_char(unsigned long addr)
151{
152  unsigned int msw, lsw;
153  unsigned char ret;
154
155  msw = addr >> 16;
156  lsw = addr & 0xffff;
157
158  asm("movf.b %0,(%2)\n" 
159      : "=e"(ret) : "d"(msw), "r"(lsw) : "memory");
160
161  return ret;
162}
163
164static inline void
165set_char(unsigned long addr, unsigned int val)
166{
167  unsigned int msw, lsw;
168
169  msw = addr >> 16;
170  lsw = addr & 0xffff;
171
172  asm("movf.b (%1),%2\n" 
173      : /* none */ : "d"(msw), "r"(lsw), "e"(val) : "memory" );
174}
175
176static inline unsigned int
177get_word(unsigned long addr)
178{
179  unsigned int ret, msw, lsw;
180
181  msw = addr >> 16;
182  lsw = addr & 0xffff;
183
184  asm("movf.w %0,(%2)\n" 
185      : "=e"(ret) : "d"(msw), "r"(lsw) : "memory" );
186
187  return ret;
188}
189
190static inline void
191set_word(unsigned long addr, unsigned int val)
192{
193  unsigned int msw, lsw;
194
195  msw = addr >> 16;
196  lsw = addr & 0xffff;
197
198  asm("movf.w (%1),%2\n" 
199      : /* none */ : "d"(msw), "r"(lsw), "e"(val) : "memory" );
200}
201
202static void
203assign_regs (struct regs *dest, const struct regs *src)
204{
205  int i;
206  char *d = (char *)dest, *s = (char *)src;
207  for (i = 0; i < sizeof (struct regs); i++)
208    *d++ = *s++;
209}
210
211/* Write out a register for a 'T' packet.  */
212
213static unsigned char *
214putreg (unsigned char *buf, int regnum, void *mem_p, int count)
215{
216  int i;
217  unsigned char ch;
218  char *mem = (char *)mem_p;
219
220  *buf++ = hexchars[regnum >> 4];
221  *buf++ = hexchars[regnum % 16];
222  *buf++ = ':';
223
224  for (i=0;i<count;i++)
225    {
226      ch = *mem++;
227      *buf++ = hexchars[ch >> 4];
228      *buf++ = hexchars[ch % 16];
229    }
230  *buf++ = ';';
231  return(buf);
232}
233
234/*
235 * This function does all command procesing for interfacing to gdb.
236 */
237void 
238handle_exception(void)
239{
240  char sigval;
241  unsigned char *ptr;
242  long addr, length;
243
244  /* reply to host that an exception has occurred */
245  sigval = 5; /* SIGTRAP is default */
246  if (ERR_DETECT_REG & UNDEF_INSN_FLAG)
247    {
248      ERR_DETECT_REG &= ~UNDEF_INSN_FLAG;
249      registers.pc -= 2;
250      if (get_word(registers.pc) != BREAKPOINT_OPCODE)
251        sigval = 4; /* SIGILL */
252    }
253  if (ERR_DETECT_REG & BAD_ADDR_FLAG)
254    {
255      ERR_DETECT_REG &= ~BAD_ADDR_FLAG;
256      sigval = 11; /* SIGSEGV */
257    }
258  if (ERR_DETECT_REG & SER0_IRQ_FLAG)
259    {
260      unsigned char ch;
261     
262      ch = getDebugChar();
263      ERR_DETECT_REG &= ~SER0_IRQ_FLAG;
264      if (ch != 0x03)
265        return;
266      sigval = 2; /* SIGINT */
267    }
268
269  finish_from_step();
270
271  /* save original context so it can be restored as a result of
272     a kill packet. */
273  if (orig_registers.pc == 0L)
274    assign_regs (&orig_registers, &registers);
275
276  if (is_running)
277    {
278      ptr = remcomBuffer;
279 
280      *ptr++ = 'T';         /* notify gdb with signo, PC, FP and SP */
281      *ptr++ = hexchars[sigval >> 4];
282      *ptr++ = hexchars[sigval & 0xf];
283 
284      ptr = putreg (ptr, PC, &registers.pc, 4);
285      ptr = putreg (ptr, FP, &registers.r[FP], 2);
286      ptr = putreg (ptr, SP, &registers.r[SP], 2);
287
288      *ptr++ = 0;
289 
290      putPacket(remcomBuffer);
291    }
292
293  while (1) {
294    char kind;
295   
296    ptr = getpacket();
297    kind = *ptr++;
298    if (kind == 'M' || kind == 'X')
299      {
300        /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */
301        /* TRY TO READ '%x,%x:'.  IF SUCCEED, SET PTR = 0 */
302        if (hexToInt(&ptr,&addr)
303            && *(ptr++) == ','
304            && hexToInt(&ptr,&length)
305            && *(ptr++) == ':')
306          {
307            if (valid_addr_range (addr, length))
308              {
309                if (kind == 'M')
310                  hex2mem(ptr, addr, length);
311                else
312                  {
313                    int i;
314                    for (i = 0; i < length; i++)
315                      if (*ptr++ == 0x7d)
316                        set_char (addr++, *ptr++ ^ 0x20);
317                      else
318                        set_char (addr++, ptr[-1]);
319                   
320                  }
321                putPacket ("OK");
322              }
323            else
324              putPacket ("E03");
325          }
326        else
327          putPacket ("E02");
328      }
329    else if (kind == 'm')
330      {
331        /* mAA..AA,LLLL  Read LLLL bytes at address AA..AA */
332        /* TRY TO READ %x,%x.  IF SUCCEED, SET PTR = 0 */
333        if (hexToInt(&ptr,&addr)
334            && *(ptr++) == ','
335            && hexToInt (&ptr,&length))
336          {
337            if (valid_addr_range (addr, length))
338              putHex (0, addr, length);
339            else
340              putPacket ("E03");
341          }
342        else
343          putPacket ("E02");
344      }
345    else if (kind == 'R')
346      {
347        if (hexToInt (&ptr, &addr))
348          registers.pc = addr;
349        putPacket ("OK");
350      }
351    else if (kind == '!')
352      putPacket ("OK");
353    else if (kind == '?')
354      putHex ('S', (unsigned long)(unsigned int)&sigval, 1);
355    else if (kind == 'g')
356      putHex (0, (unsigned long)(unsigned int)&registers, NUMREGBYTES);
357    else if (kind == 'P')
358      {
359        /* set the value of a single CPU register - return OK */
360        unsigned long regno;
361       
362        if (hexToInt (&ptr, &regno) 
363            && *ptr++ == '='
364            && regno < NUMREGS)
365          {
366            hex2mem (ptr, (unsigned long)(unsigned int)(registers.r + regno),
367                     regno == PC ? 4 : 2);
368            putPacket ("OK");
369          }
370        else
371          putPacket ("E01");
372      }
373    else if (kind == 'G')
374      {
375        /* set the value of the CPU registers - return OK */
376        hex2mem(ptr, (unsigned long)(unsigned int)&registers, NUMREGBYTES);
377        putPacket ("OK");
378      }
379    else if (kind == 's' || kind == 'c')
380      {
381        /* sAA..AA      Step one instruction from AA..AA(optional) */
382        /* cAA..AA      Continue from address AA..AA(optional) */
383        /* try to read optional parameter, pc unchanged if no parm */
384
385        is_running = 1;
386       
387        if (hexToInt(&ptr,&addr))
388          registers.pc = addr;
389       
390        if (kind == 's')        /* single-stepping */
391          prepare_to_step();
392        return;
393      }
394    else if (kind == 'k')
395      {
396        /* kill the program */
397        assign_regs (&registers, &orig_registers);
398        is_running = 0;
399        putPacket ("");
400      }
401    else
402      /* Unknown code.  Return an empty reply message. */
403      putPacket ("");
404  }
405}
406
407static int 
408hex (int ch)
409{
410  if ((ch >= '0') && (ch <= '9')) return (ch-'0');
411  if ((ch >= 'a') && (ch <= 'f')) return (ch-'a'+10);
412  if ((ch >= 'A') && (ch <= 'F')) return (ch-'A'+10);
413  return (-1);
414}
415
416/* scan for the sequence $<data>#<checksum>     */
417
418static unsigned char *
419getpacket (void)
420{
421  unsigned char *buffer = &remcomBuffer[0];
422  unsigned checksum;
423  int count;
424  char ch;
425
426  while (1)
427    {
428      /* wait around for the start character, ignore all other characters */
429      while (getDebugChar () != '$')
430        ;
431
432      checksum = 0;
433      count = 0;
434      while ((ch = getDebugChar ()) == '$')
435        ;
436
437      /* now, read until a # or end of buffer is found */
438      while (ch != '#' && count < BUFMAX - 1)
439        {
440          checksum = checksum + ch;
441          buffer[count] = ch;
442          count = count + 1;
443          ch = getDebugChar ();
444        }
445      buffer[count] = 0;
446
447      if (ch == '#')
448        {
449          unsigned xmitcsum;
450          ch = getDebugChar ();
451          xmitcsum = hex (ch) << 4;
452          ch = getDebugChar ();
453          xmitcsum += hex (ch);
454
455          /* If one of the above 'hex' calls returns -1, xmitcsum will
456             have high bits set, and so the test below will fail.  */
457
458          if ((checksum & 0xFF) != xmitcsum)
459            putDebugChar ('-'); /* failed checksum */
460          else
461            {
462              putDebugChar ('+');       /* successful transfer */
463              return &buffer[0];
464            }
465        }
466    }
467}
468
469/* send the packet in buffer.  */
470
471static void 
472putPacket (unsigned char *buffer_p)
473{
474  /*  $<packet info>#<checksum>. */
475  do {
476    unsigned checksum;
477    unsigned char *buffer = buffer_p;
478
479    putDebugChar('$');
480    checksum = 0;
481
482    while (*buffer) {
483      putDebugChar(*buffer);
484      checksum += *buffer;
485      buffer++;
486    }
487    putDebugChar('#');
488    putDebugChar(hexchars[(checksum >> 4) % 16]);
489    putDebugChar(hexchars[checksum % 16]);
490  } while (getDebugChar() != '+');
491}
492
493/* Convert the memory pointed to by mem into hex, and return it as a packet. */
494
495static void
496putHex (char c, unsigned long mem_arg, int count)
497{
498  do {
499    unsigned long mem = mem_arg;
500    int i;
501    unsigned checksum;
502
503    putDebugChar('$');
504    checksum = 0;
505
506    if (c)
507      {
508        checksum = c;
509        putDebugChar(c);
510      }
511
512    for (i = 0; i < count; i++)
513      {
514        unsigned char c = get_char (mem);
515        char ch = hexchars[c >> 4];
516        putDebugChar(ch);
517        checksum += ch;
518        ch = hexchars[c % 16];
519        putDebugChar(ch);
520        checksum += ch;
521        mem++;
522      }
523    putDebugChar('#');
524    putDebugChar(hexchars[(checksum >> 4) % 16]);
525    putDebugChar(hexchars[checksum % 16]);
526  } while (getDebugChar() != '+');
527}
528
529/* Function: gdb_write(char *, int)
530   Make gdb write n bytes to stdout (not assumed to be null-terminated). */
531 
532void
533gdb_write (char *data, int len)
534{
535  ERR_DETECT_REG &= ~SER0_IRQ_ENA;
536  putHex ('O', (unsigned long)(unsigned int)data, len);
537  ERR_DETECT_REG |= SER0_IRQ_ENA;
538}
539
540int
541gdb_read (char *buf, int nbytes)
542{
543  int i = 0;
544
545  ERR_DETECT_REG &= ~SER0_IRQ_ENA;
546  for (i = 0; i < nbytes; i++)
547    {
548      *(buf + i) = getDebugChar();
549      if ((*(buf + i) == '\n') || (*(buf + i) == '\r'))
550        {
551          (*(buf + i + 1)) = 0;
552          break;
553        }
554    }
555  ERR_DETECT_REG |= SER0_IRQ_ENA;
556  return (i);
557}
558
559static int
560valid_addr_range (unsigned long mem, int count)
561{
562  unsigned long last = mem + count - 1;
563
564  if (last < 0x800L)
565    return 1;
566
567  if (mem < 0x7f00L)
568    return 0;
569
570  if (last > 0x7ffffL)
571    return 0;
572
573  return 1;
574}
575
576/* Convert the hex array pointed to by buf into binary to be placed in mem.
577   Return a pointer to the character AFTER the last byte written. */
578
579static void
580hex2mem (unsigned char *buf, unsigned long mem, int count)
581{
582  int i;
583  unsigned char ch;
584
585  for (i=0;i<count;i++)
586    {
587      ch = hex(*buf++) << 4;
588      ch = ch + hex(*buf++);
589      set_char (mem++, ch);
590    }
591}
592
593/**********************************************/
594/* WHILE WE FIND NICE HEX CHARS, BUILD AN INT */
595/* RETURN NUMBER OF CHARS PROCESSED           */
596/**********************************************/
597static int 
598hexToInt (unsigned char **ptr, long *intValue)
599{
600  int numChars = 0;
601  int hexValue;
602
603  *intValue = 0;
604  while (**ptr)
605    {
606      hexValue = hex(**ptr);
607      if (hexValue >=0)
608        {
609          *intValue = (*intValue <<4) | (unsigned) hexValue;
610          numChars ++;
611        }
612      else
613        break;
614      (*ptr)++;
615    }
616  return (numChars);
617}
618
619
620/* Function: opcode_size
621   Determine number of bytes in full opcode by examining first word.
622*/
623static int
624opcode_size(unsigned int opcode)
625{
626  if ((opcode & 0xff00) == 0)
627    return 2;
628
629  if ((opcode & 0xf800) == 0)
630    return 4;
631
632  if ((opcode & 0xf800) == 0x7800)
633    return 4;
634
635  if ((opcode & 0xf000) == 0xc000)
636    return 4;
637
638  if ((opcode & 0xf100) == 0x2000)
639    return 4;
640
641  if ((opcode & 0xfff0) == 0x30e0)
642    return 4;
643
644  if ((opcode & 0xf008) == 0x6008)
645    return 4;
646
647  if ((opcode & 0xf808) == 0x7008)
648    return 4;
649
650  opcode >>= 8;
651  if (opcode == 0x0c || opcode == 0x0d || opcode == 0x31)
652    return 4;
653
654  return 2;
655}
656
657static struct {
658  unsigned long  addr;
659  unsigned long  addr2;
660  unsigned int   opcode;
661  unsigned int   opcode2;
662} stepinfo;
663
664/* Function: prepare_to_step
665   Called from handle_exception to prepare the user program to single-step.
666   Places a trap instruction after the target instruction, with special
667   extra handling for branch instructions.
668*/
669
670static void
671prepare_to_step(void)
672{
673  unsigned long pc = registers.pc;
674  unsigned long next_pc, next_pc2;
675  unsigned int  op, op2, sp;
676  unsigned char op_msb, op_lsb;
677  int  r12;
678  char r8;
679
680  op = get_word(pc);
681  op_msb = (op >> 8) & 0xff;
682  op_lsb = op & 0xff;
683  op2 = get_word(pc + 2);
684  next_pc = pc + opcode_size(op);
685  next_pc2 = 0;
686
687  if (op_msb == 0)
688    {
689      if (op_lsb == 2)
690        {
691          /* IRET */
692          sp = registers.r[SP];
693          next_pc = *(unsigned *)(sp - 4);
694          next_pc = (next_pc << 16) | *(unsigned *)(sp - 6);
695        }
696      else if (op_lsb == 3)
697        {
698          /* RET */
699          sp = registers.r[SP];
700          next_pc = *(unsigned *)(sp - 2);
701          next_pc = (next_pc << 16) | *(unsigned *)(sp - 4);
702        }
703      else
704        {
705          op2 = op_lsb & 0xf0;
706          if (op2 && op2 < 0x40)
707            {
708              /* {CALLR,BR,ICALLR} Rs */
709              next_pc = (pc + 2) + (int)registers.r[op_lsb & 0xf];
710            }
711          else if (op2 < 0x80 || op2 == 0xa0 || op2 == 0xb0)
712            {
713              /* {JMP,ICALL,CALL} Rb,Rs */
714              next_pc = registers.r[(op_lsb & 0x10) ? 9 : 8];
715              next_pc = (next_pc << 16) | (unsigned int)registers.r[op_lsb & 0xf];
716            }
717        }
718    }
719  else if (op_msb < 4)
720    {
721      /* {CALLF,JMPF,ICALLF} a24 */
722      next_pc = ((unsigned long)op2) << 8;
723      next_pc |= op_lsb;
724    }
725  else if (op_msb < 8)
726    {
727      if ((op2 & 0xf000) == 0)
728        {
729            /* Bx Rd,#imm4,r12 */
730            /* Bx Rd,Rs,r12    */
731            r12 = op2 << 4;
732            r12 >>= 4;
733            next_pc2 = (pc + 4) + r12;
734        }
735    }
736  else if (op_msb == 0x0c || op_msb == 0x0d || (op_msb & 0xf1) == 0x20 ||
737           ((op_msb >= 0x7c && op_msb <= 0x7f) && (op2 & 0x8000) == 0))
738    {
739      /* Bxx Rd,Rs,r12    */
740      /* Bxx Rd,#imm8,r12 */
741      /* Bx  m8,#imm3,r12 */
742      /* Bx s8,#imm3,r12  */
743      r12 = op2 << 4;
744      r12 >>= 4;
745      next_pc2 = (pc + 4) + r12;
746    }
747  else if ((op_msb & 0xf0) == 0x10)
748    {
749      /* {BR,CALLR} r12 */
750      r12 = (op & 0xffe) << 4;
751      r12 >>= 4;
752      next_pc = (pc + 2) + r12;
753    }
754  else if ((op_msb & 0xe0) == 0xc0)
755    {
756      /* Bxx Rx,#imm16,r8 */
757      /* TBxx r8 */
758      r8 = op_lsb;
759      next_pc2 = next_pc + r8;
760    }
761
762  stepinfo.addr = next_pc;
763  stepinfo.opcode = get_word(next_pc);
764  set_word(next_pc, BREAKPOINT_OPCODE);
765
766  if (next_pc2)
767    {
768      stepinfo.addr2 = next_pc2;
769      stepinfo.opcode2 = get_word(next_pc2);
770      set_word(next_pc2, BREAKPOINT_OPCODE);
771    }
772}
773
774/* Function: finish_from_step
775   Called from handle_exception to finish up when the user program
776   returns from a single-step.  Replaces the instructions that had
777   been overwritten by breakpoint. */
778
779static void
780finish_from_step (void)
781{
782  if (stepinfo.addr)    /* anything to do? */
783    {
784      set_word(stepinfo.addr, stepinfo.opcode);
785      stepinfo.addr = 0;
786      if (stepinfo.addr2)
787        {
788          set_word(stepinfo.addr2, stepinfo.opcode2);
789          stepinfo.addr2 = 0;
790        }
791    }
792}
793
794
795/*
796 * UART support
797 */
798#define UART0_BASE 0x7f38
799#define UART1_BASE 0x7f48
800
801#define UART_CR(base)  (*(volatile unsigned char *)(base))
802#define UART_RXD(base) (*(volatile unsigned int *)((base) + 2))
803#define UART_TXD(base) (*(volatile unsigned int *)((base) + 4))
804
805#define UART_CR_RUN       0x80
806#define UART_CR_ERR       0x40
807#define UART_CR_BAUD_115k 0x20
808#define UART_CR_PARITY    0x10
809#define UART_CR_TXEMPTY   0x08
810#define UART_CR_TXIEN     0x04
811#define UART_CR_RXRDY     0x02
812#define UART_CR_RXIEN     0x01
813
814#define DBG_UART UART0_BASE
815
816static void
817putDebugChar(unsigned ch)
818{
819  while ((UART_CR(DBG_UART) & UART_CR_TXEMPTY) == 0) ;
820
821  UART_TXD(DBG_UART) = ch;
822}
823
824static unsigned char
825getDebugChar(void)
826{
827  while ((UART_CR(DBG_UART) & UART_CR_RXRDY) == 0) ;
828
829  return UART_RXD(DBG_UART);
830}
831
832void
833uart_init(void)
834{
835  UART_CR(DBG_UART) |= (UART_CR_RUN | UART_CR_RXIEN);
836}
837
Note: See TracBrowser for help on using the repository browser.