Add bwio
authorBill Cowan <wmcowan@cgl.uwaterloo.ca>
Sat, 17 Jul 2010 20:35:33 +0000 (16:35 -0400)
committerMichael Spang <mspang@csclub.uwaterloo.ca>
Sat, 17 Jul 2010 20:53:32 +0000 (16:53 -0400)
include/bwio.h [new file with mode: 0644]
include/ts7200.h [new file with mode: 0644]
src/Makefile [new file with mode: 0644]
src/bwio.c [new file with mode: 0644]
test/Makefile [new file with mode: 0644]
test/iotest.c [new file with mode: 0644]
test/iotest.h [new file with mode: 0644]
test/iotest.map [new file with mode: 0644]
test/orex.ld [new file with mode: 0644]

diff --git a/include/bwio.h b/include/bwio.h
new file mode 100644 (file)
index 0000000..8319f86
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * bwio.h
+ */
+
+typedef char *va_list;
+
+#define __va_argsiz(t) \
+               (((sizeof(t) + sizeof(int) - 1) / sizeof(int)) * sizeof(int))
+
+#define va_start(ap, pN) ((ap) = ((va_list) __builtin_next_arg(pN)))
+
+#define va_end(ap)     ((void)0)
+
+#define va_arg(ap, t)  \
+                (((ap) = (ap) + __va_argsiz(t)), *((t*) (void*) ((ap) - __va_argsiz(t))))
+
+#define COM1   0
+#define COM2   1
+
+#define ON     1
+#define        OFF     0
+
+int bwsetfifo( int channel, int state );
+
+int bwsetspeed( int channel, int speed );
+
+int bwputc( int channel, char c );
+
+int bwgetc( int channel );
+
+int bwputx( int channel, char c );
+
+int bwputstr( int channel, char *str );
+
+int bwputr( int channel, unsigned int reg );
+
+void bwputw( int channel, int n, char fc, char *bf );
+
+void bwprintf( int channel, char *format, ... );
diff --git a/include/ts7200.h b/include/ts7200.h
new file mode 100644 (file)
index 0000000..50890ad
--- /dev/null
@@ -0,0 +1,84 @@
+/*
+ * ts7200.h - definitions describing the ts7200 peripheral registers
+ *
+ * Specific to the TS-7200 ARM evaluation board
+ *
+ */
+
+#define        TIMER1_BASE     0x80810000
+#define        TIMER2_BASE     0x80810020
+#define        TIMER3_BASE     0x80810080
+
+#define        LDR_OFFSET      0x00000000      // 16/32 bits, RW
+#define        VAL_OFFSET      0x00000004      // 16/32 bits, RO
+#define CRTL_OFFSET    0x00000008      // 3 bits, RW
+       #define ENABLE_MASK     0x00000080
+       #define MODE_MASK       0x00000040
+       #define CLKSEL_MASK     0x00000008
+#define CLR_OFFSET     0x0000000c      // no data, WO
+
+
+#define LED_ADDRESS    0x80840020
+       #define LED_NONE        0x0
+       #define LED_GREEN       0x1
+       #define LED_RED         0x2
+       #define LED_BOTH        0x3
+
+#define COM1   0
+#define COM2   1
+
+#define IRDA_BASE      0x808b0000
+#define UART1_BASE     0x808c0000
+#define UART2_BASE     0x808d0000
+
+// All the below registers for UART1
+// First nine registers (up to Ox28) for UART 2
+
+#define UART_DATA_OFFSET       0x0     // low 8 bits
+       #define DATA_MASK       0xff
+#define UART_RSR_OFFSET                0x4     // low 4 bits
+       #define FE_MASK         0x1
+       #define PE_MASK         0x2
+       #define BE_MASK         0x4
+       #define OE_MASK         0x8
+#define UART_LCRH_OFFSET       0x8     // low 7 bits
+       #define BRK_MASK        0x1
+       #define PEN_MASK        0x2     // parity enable
+       #define EPS_MASK        0x4     // even parity
+       #define STP2_MASK       0x8     // 2 stop bits
+       #define FEN_MASK        0x10    // fifo
+       #define WLEN_MASK       0x60    // word length
+#define UART_LCRM_OFFSET       0xc     // low 8 bits
+       #define BRDH_MASK       0xff    // MSB of baud rate divisor
+#define UART_LCRL_OFFSET       0x10    // low 8 bits
+       #define BRDL_MASK       0xff    // LSB of baud rate divisor
+#define UART_CTLR_OFFSET       0x14    // low 8 bits
+       #define UARTEN_MASK     0x1
+       #define MSIEN_MASK      0x8     // modem status int
+       #define RIEN_MASK       0x10    // receive int
+       #define TIEN_MASK       0x20    // transmit int
+       #define RTIEN_MASK      0x40    // receive timeout int
+       #define LBEN_MASK       0x80    // loopback 
+#define UART_FLAG_OFFSET       0x18    // low 8 bits
+       #define CTS_MASK        0x1
+       #define DCD_MASK        0x2
+       #define DSR_MASK        0x4
+       #define TXBUSY_MASK     0x8
+       #define RXFE_MASK       0x10    // Receive buffer empty
+       #define TXFF_MASK       0x20    // Transmit buffer full
+       #define RXFF_MASK       0x40    // Receive buffer full
+       #define TXFE_MASK       0x80    // Transmit buffer empty
+#define UART_INTR_OFFSET       0x1c
+#define UART_DMAR_OFFSET       0x28
+
+// Specific to UART1
+
+#define UART_MDMCTL_OFFSET     0x100
+#define UART_MDMSTS_OFFSET     0x104
+#define UART_HDLCCTL_OFFSET    0x20c
+#define UART_HDLCAMV_OFFSET    0x210
+#define UART_HDLCAM_OFFSET     0x214
+#define UART_HDLCRIB_OFFSET    0x218
+#define UART_HDLCSTS_OFFSET    0x21c
+
+
diff --git a/src/Makefile b/src/Makefile
new file mode 100644 (file)
index 0000000..2ba126a
--- /dev/null
@@ -0,0 +1,33 @@
+#
+# Makefile for busy-wait IO library
+#
+XCC     = gcc
+AS     = as
+AR     = ar
+CFLAGS  = -c -fPIC -Wall -I. -I../include -mcpu=arm920t -msoft-float
+# -g: include hooks for gdb
+# -c: only compile
+# -mcpu=arm920t: generate code for the 920t architecture
+# -fpic: emit position-independent code
+# -Wall: report all warnings
+# -msoft-float: use software for floating point
+
+ASFLAGS        = -mcpu=arm920t -mapcs-32
+# -mapcs-32: always create a complete stack frame
+
+ARFLAGS = rcs
+
+all:  bwio.a 
+
+bwio.s: bwio.c 
+       $(XCC) -S $(CFLAGS) bwio.c
+
+bwio.o: bwio.s
+       $(AS) $(ASFLAGS) -o bwio.o bwio.s
+
+bwio.a: bwio.o
+       $(AR) $(ARFLAGS) $@ bwio.o
+
+
+clean:
+       -rm -f *.s *.a *.o
diff --git a/src/bwio.c b/src/bwio.c
new file mode 100644 (file)
index 0000000..5bccaf1
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * bwio.c - busy-wait I/O routines for diagnosis
+ *
+ * Specific to the TS-7200 ARM evaluation board
+ *
+ */
+
+#include <ts7200.h>
+#include <bwio.h>
+
+/*
+ * The UARTs are initialized by RedBoot to the following state
+ *     115,200 bps
+ *     8 bits
+ *     no parity
+ *     fifos enabled
+ */
+int bwsetfifo( int channel, int state ) {
+       int *line, buf;
+       switch( channel ) {
+       case COM1:
+               line = (int *)( UART1_BASE + UART_LCRH_OFFSET );
+               break;
+       case COM2:
+               line = (int *)( UART2_BASE + UART_LCRH_OFFSET );
+               break;
+       default:
+               return -1;
+               break;
+       }
+       buf = *line;
+       buf = state ? buf | FEN_MASK : buf & ~FEN_MASK;
+       *line = buf;
+       return 0;
+}
+
+int bwsetspeed( int channel, int speed ) {
+       int *high, *low;
+       switch( channel ) {
+       case COM1:
+               high = (int *)( UART1_BASE + UART_LCRM_OFFSET );
+               low = (int *)( UART1_BASE + UART_LCRL_OFFSET );
+               break;
+       case COM2:
+               high = (int *)( UART2_BASE + UART_LCRM_OFFSET );
+               low = (int *)( UART2_BASE + UART_LCRL_OFFSET );
+               break;
+       default:
+               return -1;
+               break;
+       }
+       switch( speed ) {
+       case 115200:
+               *high = 0x0;
+               *low = 0x3;
+               return 0;
+       case 2400:
+               *high = 0x0;
+               *low = 0x90;
+               return 0;
+       default:
+               return -1;
+       }
+}
+
+int bwputc( int channel, char c ) {
+       int *flags, *data;
+       switch( channel ) {
+       case COM1:
+               flags = (int *)( UART1_BASE + UART_FLAG_OFFSET );
+               data = (int *)( UART1_BASE + UART_DATA_OFFSET );
+               break;
+       case COM2:
+               flags = (int *)( UART2_BASE + UART_FLAG_OFFSET );
+               data = (int *)( UART2_BASE + UART_DATA_OFFSET );
+               break;
+       default:
+               return -1;
+               break;
+       }
+       while( ( *flags & TXFF_MASK ) ) ;
+       *data = c;
+       return 0;
+}
+
+char c2x( char ch ) {
+       if ( (ch <= 9) ) return '0' + ch;
+       return 'a' + ch - 10;
+}
+
+int bwputx( int channel, char c ) {
+       char chh, chl;
+
+       chh = c2x( c / 16 );
+       chl = c2x( c % 16 );
+       bwputc( channel, chh );
+       return bwputc( channel, chl );
+}
+
+int bwputr( int channel, unsigned int reg ) {
+       int byte;
+       char *ch = (char *) &reg;
+
+       for( byte = 3; byte >= 0; byte-- ) bwputx( channel, ch[byte] );
+       return bwputc( channel, ' ' );
+}
+
+int bwputstr( int channel, char *str ) {
+       while( *str ) {
+               if( bwputc( channel, *str ) < 0 ) return -1;
+               str++;
+       }
+       return 0;
+}
+
+void bwputw( int channel, int n, char fc, char *bf ) {
+       char ch;
+       char *p = bf;
+
+       while( *p++ && n > 0 ) n--;
+       while( n-- > 0 ) bwputc( channel, fc );
+       while( ( ch = *bf++ ) ) bwputc( channel, ch );
+}
+
+int bwgetc( int channel ) {
+       int *flags, *data;
+       unsigned char c;
+
+       switch( channel ) {
+       case COM1:
+               flags = (int *)( UART1_BASE + UART_FLAG_OFFSET );
+               data = (int *)( UART1_BASE + UART_DATA_OFFSET );
+               break;
+       case COM2:
+               flags = (int *)( UART2_BASE + UART_FLAG_OFFSET );
+               data = (int *)( UART2_BASE + UART_DATA_OFFSET );
+               break;
+       default:
+               return -1;
+               break;
+       }
+       while ( !( *flags & RXFF_MASK ) ) ;
+       c = *data;
+       return c;
+}
+
+int bwa2d( char ch ) {
+       if( ch >= '0' && ch <= '9' ) return ch - '0';
+       if( ch >= 'a' && ch <= 'f' ) return ch - 'a' + 10;
+       if( ch >= 'A' && ch <= 'F' ) return ch - 'A' + 10;
+       return -1;
+}
+
+char bwa2i( char ch, char **src, int base, int *nump ) {
+       int num, digit;
+       char *p;
+
+       p = *src; num = 0;
+       while( ( digit = bwa2d( ch ) ) >= 0 ) {
+               if ( digit > base ) break;
+               num = num*base + digit;
+               ch = *p++;
+       }
+       *src = p; *nump = num;
+       return ch;
+}
+
+void bwui2a( unsigned int num, unsigned int base, char *bf ) {
+       int n = 0;
+       int dgt;
+       unsigned int d = 1;
+       
+       while( (num / d) >= base ) d *= base;
+       while( d != 0 ) {
+               dgt = num / d;
+               num %= d;
+               d /= base;
+               if( n || dgt > 0 || d == 0 ) {
+                       *bf++ = dgt + ( dgt < 10 ? '0' : 'a' - 10 );
+                       ++n;
+               }
+       }
+       *bf = 0;
+}
+
+void bwi2a( int num, char *bf ) {
+       if( num < 0 ) {
+               num = -num;
+               *bf++ = '-';
+       }
+       bwui2a( num, 10, bf );
+}
+
+void bwformat ( int channel, char *fmt, va_list va ) {
+       char bf[12];
+       char ch, lz;
+       int w;
+
+       
+       while ( ( ch = *(fmt++) ) ) {
+               if ( ch != '%' )
+                       bwputc( channel, ch );
+               else {
+                       lz = 0; w = 0;
+                       ch = *(fmt++);
+                       switch ( ch ) {
+                       case '0':
+                               lz = 1; ch = *(fmt++);
+                               break;
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                               ch = bwa2i( ch, &fmt, 10, &w );
+                               break;
+                       }
+                       switch( ch ) {
+                       case 0: return;
+                       case 'c':
+                               bwputc( channel, va_arg( va, char ) );
+                               break;
+                       case 's':
+                               bwputw( channel, w, 0, va_arg( va, char* ) );
+                               break;
+                       case 'u':
+                               bwui2a( va_arg( va, unsigned int ), 10, bf );
+                               bwputw( channel, w, lz, bf );
+                               break;
+                       case 'd':
+                               bwi2a( va_arg( va, int ), bf );
+                               bwputw( channel, w, lz, bf );
+                               break;
+                       case 'x':
+                               bwui2a( va_arg( va, unsigned int ), 16, bf );
+                               bwputw( channel, w, lz, bf );
+                               break;
+                       case '%':
+                               bwputc( channel, ch );
+                               break;
+                       }
+               }
+       }
+}
+
+void bwprintf( int channel, char *fmt, ... ) {
+        va_list va;
+
+        va_start(va,fmt);
+        bwformat( channel, fmt, va );
+        va_end(va);
+}
+
diff --git a/test/Makefile b/test/Makefile
new file mode 100644 (file)
index 0000000..b58aa81
--- /dev/null
@@ -0,0 +1,31 @@
+#
+# Makefile for busy-wait IO tests
+#
+XCC     = gcc
+AS     = as
+LD      = ld
+CFLAGS  = -c -fPIC -Wall -I. -I../include -mcpu=arm920t -msoft-float
+# -g: include hooks for gdb
+# -c: only compile
+# -mcpu=arm920t: generate code for the 920t architecture
+# -fpic: emit position-independent code
+# -Wall: report all warnings
+
+ASFLAGS        = -mcpu=arm920t -mapcs-32
+# -mapcs: always generate a complete stack frame
+
+LDFLAGS = -init main -Map iotest.map -N  -T orex.ld -L/u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2 -L../lib
+
+all:  iotest.s iotest.elf
+
+iotest.s: iotest.c iotest.h
+       $(XCC) -S $(CFLAGS) iotest.c
+
+iotest.o: iotest.s
+       $(AS) $(ASFLAGS) -o iotest.o iotest.s
+
+iotest.elf: iotest.o
+       $(LD) $(LDFLAGS) -o $@ iotest.o -lbwio -lgcc
+
+clean:
+       -rm -f iotest.elf *.s *.o iotest.map
diff --git a/test/iotest.c b/test/iotest.c
new file mode 100644 (file)
index 0000000..0137435
--- /dev/null
@@ -0,0 +1,21 @@
+ /*
+ * iotest.c
+ */
+
+#include <bwio.h>
+#include <ts7200.h>
+
+int main( int argc, char* argv[] ) {
+       char str[] = "Hello\n\r";
+       bwsetfifo( COM2, OFF );
+       bwputstr( COM2, str );
+       bwputw( COM2, 10, '*', str );
+       bwprintf( COM2, "Hello world.\n\r" );
+       bwprintf( COM2, "%s world%u.\n\r", "Well, hello", 23 );
+       bwprintf( COM2, "%d worlds for %u person.\n\r", -23, 1 );
+       bwprintf( COM2, "%x worlds for %d people.\n\r", -23, 723 );
+       str[0] = bwgetc( COM2 );
+       bwprintf( COM2, "%s", str );
+       return 0;
+}
+
diff --git a/test/iotest.h b/test/iotest.h
new file mode 100644 (file)
index 0000000..8b13789
--- /dev/null
@@ -0,0 +1 @@
+
diff --git a/test/iotest.map b/test/iotest.map
new file mode 100644 (file)
index 0000000..96e3932
--- /dev/null
@@ -0,0 +1,100 @@
+Archive member included because of file (symbol)
+
+../lib/libbwio.a(bwio.o)      iotest.o (bwsetfifo)
+/u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_udivsi3.o)
+                              ../lib/libbwio.a(bwio.o) (__udivsi3)
+/u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_umodsi3.o)
+                              ../lib/libbwio.a(bwio.o) (__umodsi3)
+/u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_dvmd_tls.o)
+                              /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_udivsi3.o) (__div0)
+
+Memory Configuration
+
+Name             Origin             Length             Attributes
+ram              0x0000000000000000 0x0000000002000000
+rom              0x0000000060000000 0x0000000000800000
+*default*        0x0000000000000000 0xffffffffffffffff
+
+Linker script and memory map
+
+
+data            0x0000000000000000        0x0
+                0x0000000000000000                _DataStart = .
+ *(.data)
+                0x0000000000000000                _DataEnd = .
+
+bss             0x0000000000000000        0x0
+                0x0000000000000000                _BssStart = .
+ *(.bss)
+                0x0000000000000000                _BssEnd = .
+
+text            0x0000000000000000      0xfe4
+ *(.text)
+ .text          0x0000000000000000      0x134 iotest.o
+                0x0000000000000000                main
+ .text          0x0000000000000134      0xc54 ../lib/libbwio.a(bwio.o)
+                0x00000000000004ac                bwputr
+                0x0000000000000a18                bwi2a
+                0x0000000000000134                bwsetfifo
+                0x0000000000000308                bwputc
+                0x0000000000000768                bwa2d
+                0x00000000000001fc                bwsetspeed
+                0x00000000000003cc                c2x
+                0x0000000000000810                bwa2i
+                0x00000000000006b0                bwgetc
+                0x00000000000008d4                bwui2a
+                0x0000000000000a7c                bwformat
+                0x00000000000005a8                bwputw
+                0x0000000000000d50                bwprintf
+                0x000000000000042c                bwputx
+                0x000000000000052c                bwputstr
+ .text          0x0000000000000d88      0x110 /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_udivsi3.o)
+                0x0000000000000d88                __udivsi3
+                0x0000000000000e80                __aeabi_uidivmod
+ .text          0x0000000000000e98       0xcc /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_umodsi3.o)
+                0x0000000000000e98                __umodsi3
+ .text          0x0000000000000f64        0x4 /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_dvmd_tls.o)
+                0x0000000000000f64                __aeabi_ldiv0
+                0x0000000000000f64                __div0
+                0x0000000000000f64                __aeabi_idiv0
+ *(.got)
+ *(.got.plt)
+ .got.plt       0x0000000000000f68        0xc iotest.o
+                0x0000000000000f68                _GLOBAL_OFFSET_TABLE_
+ *(.rodata)
+ .rodata        0x0000000000000f74       0x70 iotest.o
+ *(.glue_7)
+ *(.glue_7t)
+
+.rel.dyn
+LOAD iotest.o
+LOAD ../lib/libbwio.a
+LOAD /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a
+OUTPUT(iotest.elf elf32-littlearm)
+
+.comment        0x0000000000000000       0x24
+ .comment       0x0000000000000000       0x12 iotest.o
+ .comment       0x0000000000000012       0x12 ../lib/libbwio.a(bwio.o)
+
+.debug_line     0x0000000000000000      0x14f
+ .debug_line    0x0000000000000000       0x86 /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_udivsi3.o)
+ .debug_line    0x0000000000000086       0x6f /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_umodsi3.o)
+ .debug_line    0x00000000000000f5       0x5a /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_dvmd_tls.o)
+
+.debug_info     0x0000000000000000      0x153
+ .debug_info    0x0000000000000000       0x71 /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_udivsi3.o)
+ .debug_info    0x0000000000000071       0x71 /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_umodsi3.o)
+ .debug_info    0x00000000000000e2       0x71 /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_dvmd_tls.o)
+
+.debug_abbrev   0x0000000000000000       0x3c
+ .debug_abbrev  0x0000000000000000       0x14 /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_udivsi3.o)
+ .debug_abbrev  0x0000000000000014       0x14 /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_umodsi3.o)
+ .debug_abbrev  0x0000000000000028       0x14 /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_dvmd_tls.o)
+
+.debug_aranges  0x0000000000000000       0x60
+ .debug_aranges
+                0x0000000000000000       0x20 /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_udivsi3.o)
+ .debug_aranges
+                0x0000000000000020       0x20 /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_umodsi3.o)
+ .debug_aranges
+                0x0000000000000040       0x20 /u/wbcowan/gnuarm-4.0.2/lib/gcc/arm-elf/4.0.2/libgcc.a(_dvmd_tls.o)
diff --git a/test/orex.ld b/test/orex.ld
new file mode 100644 (file)
index 0000000..127dd3e
--- /dev/null
@@ -0,0 +1,34 @@
+ENTRY (main)
+
+MEMORY
+{
+ram : ORIGIN = 0x00000000, LENGTH = 32M
+rom : ORIGIN = 0x60000000, LENGTH = 8M
+}
+
+SECTIONS
+{
+data : /* Initialized data. */
+{
+_DataStart = . ;
+*(.data)
+_DataEnd = . ;
+} >ram
+
+bss : /* Uninitialized data. */
+{
+_BssStart = . ;
+*(.bss)
+_BssEnd = . ;
+} >ram
+
+text : /* The actual instructions. */
+{
+*(.text)
+*(.got)
+*(.got.plt)
+*(.rodata)
+*(.glue_7)
+*(.glue_7t)
+} >ram
+}