Improved console printing; 2nd, 4th, ... args still ignored on tic55x?
authorRick van Rein <vanrein@hwdev.(none)>
Fri, 6 May 2011 10:07:06 +0000 (10:07 +0000)
committerRick van Rein <vanrein@hwdev.(none)>
Fri, 6 May 2011 10:07:06 +0000 (10:07 +0000)
include/0cpm/cons.h
src/function/Kconfig
src/function/Kconfig.devel
src/function/develtest/netconsole.c
src/function/netconsole.c

index 7aa9920..46a2aec 100644 (file)
@@ -2,16 +2,15 @@
  *
  * This implements logging over an LLC console, where supported.
  * Messages are written to the log when sent as bottom_printf (fmt, ...)
- * and will always be prefixed with __FILE__ and __LINE__ information.
- * The implementation is through a bottom_console_printf() call.
- * If the console is not compiled in, there will be no code generated
- * for such calls.
+ * This is passed to the console routines through inline functions, as
+ * not all embedded compilers support varargs in #defines.  The functions
+ * should reduce to no code without CONFIG_FUNCTION_DEVEL_NETCONSOLE.
  *
- * For portability to all platforms, there must always be at least one
- * argument, even if it is not used.  There are ways to work around this
- * constraint, as described on the link below, but relying on it would
- * be asking for trouble when targetting all kinds of embedded compilers.
- * http://blog.mellenthin.de/archives/2010/10/26/portable-__va_args__-macros-for-linux-hp-ux-solaris-and-aix/
+ * The formats are very close to those of printf():
+ *  - %s %c %d %x print string or (NULL), char, decimal and hexadecimal
+ *  - %p prints a pointer in hexadecimal notation
+ *  - %d and %x print unsigned int; %ld and %lx print unsigned long int
+ *  - field lengths like %12s attach spaces; %5d and %4x prefix zeroes
  *
  * From: Rick van Rein <rick@openfortress.nl>
  */
index 6595bdd..04e24d4 100644 (file)
@@ -88,15 +88,19 @@ config FUNCTION_DEVEL_NETCONSOLE
        help
          Direct console traffic for the main application to the network.
 
-         The protocol used for this network console is Logical Link Control.
-         This is an ethernet-level protocol, so it will only work locally.
-
-         This console can also be selected as a main function for the
-         image being built, to test network connectivity.
-
-         TODO: ports
-
-         This facility is normally only of use during development.
+         The protocol used for this network console is Logical Link Control
+         or IEEE 802.2, more to the point LLC2 which is a bit like TCP but
+         directly on top of Ethernet.  It is only accessible to directly
+         connected computers on the same LAN, so this is very suitable to
+         release console information to a LAN.
+
+         This console can be an add-on module for other targets, or it can
+         be selected as a development target to become the main function for
+         the image being built.  In that capacity it is a good test for the
+         network drivers.
+
+         This facility is normally only of use during development, but may
+         nonetheless be compiled into end-user modules.
 
 config FUNCTION_FIRMWARE_UPGRADES
        bool "Support firmware upgrades"
index e0f58fd..22c8340 100644 (file)
@@ -31,8 +31,13 @@ config MAINFUNCTION_DEVEL_NETWORK
        depends on DEVEL
        select FUNCTION_DEVEL_NETCONSOLE
        help
-         This test runs a networked console.  In addition to the usual console
-         functions, respond to any text sent by mapping it to uppercase.
+         This test runs a networked console.  The test will print information
+         about incoming network packets and ignore traffic sent to the device.
+
+         Note that the performance is not based on timers, but instead
+         triggered when something is logged.  This may lead to delays in the
+         delivery, of bursty sends that cause rejects at the LLC2 level.
+         This is really just a test, rather than a perfect application.
 
          The details of the networked console are described under the
          add-on function for this console, one menu level up.
index 434d5f7..f218b83 100644 (file)
@@ -74,13 +74,13 @@ static uint8_t llc_ua [6 + 6 + 2 + 3];
 static uint8_t llc_rr [6 + 6 + 2 + 4];
 static uint8_t llc_sent;
 static uint8_t llc_received;
+static uint8_t llc_input;
 
 
 /* Dummy LLC2 send routine, ignoring "cnx" as there is just one LLC2 connection.
- * This is out-only, so N(R) always sends as 0x00 and N(S) increments.
  * Before sending, the routine will first establish whether the last send
- * was successful; if not, it will repeat that.  The return value is true if
- * at least the send was done, relying on future calls to resend if need be.
+ * was successful; if not, it will repeat that.  The return value is true if at
+ * least the new send was done, relying on future calls to resend if need be.
  */
 uint8_t llc_pkt [100];
 uint16_t llc_pktlen;
@@ -102,7 +102,7 @@ bool netsend_llc2 (struct llc2 *cnx, uint8_t *data, uint16_t datalen) {
                llc_pkt [14] = peer_sap;                // DSAP
                llc_pkt [15] = 20;                      // SSAP
                llc_pkt [16] = llc_sent << 1;           // N(S) = 0x00, information frame
-               llc_pkt [17] = 0x00;                    // N(R) = sent-up-to-here, low bit reset
+               llc_pkt [17] = llc_input << 1;          // N(R) = sent-up-to-here, low bit reset
                memcpy (llc_pkt + 18, data, datalen);
                llc_pktlen = 6 + 6 + 2 + 4 + datalen;
                llc_sent++;
@@ -130,7 +130,7 @@ void selfish_llc2_handler (uint8_t *pkt, uint16_t pktlen) {
        }
 #endif
        if (typelen > 1500) {
-               // bottom_printf ("Traffic is not LLC but protocol 0x%x\n", (unsigned int) typelen);
+               bottom_printf ("Traffic is not LLC but protocol 0x%4x\n", (unsigned int) typelen);
                return;
        }
        if ((typelen > 64) && (typelen != pktlen)) {
@@ -158,7 +158,7 @@ void selfish_llc2_handler (uint8_t *pkt, uint16_t pktlen) {
        if (cmd == 0x007f) {                            // SABME (llc.connect)
                memcpy (peer_mac, pkt + 6, 6);
                peer_sap = pkt [15] & 0xfe;
-               llc_sent = llc_received = 0x00;
+               llc_sent = llc_received = llc_input = 0x00;
                llc_connected = true;
                netcons_connect (&llc2_dummy_handle);
                ack = true;
@@ -179,7 +179,7 @@ void selfish_llc2_handler (uint8_t *pkt, uint16_t pktlen) {
        } else if ((cmd & 0x0007) == 0x0001) {          // Receiver ready / Receiver Reject
                llc_received = (cmd >> 9);
        } else {
-               bottom_printf ("Selfishly ignoring LLC traffic with cmd bytes 0x%x 0x%x\n", (uint32_t) pkt [16], (uint32_t) pkt [17]);
+               bottom_printf ("Selfishly ignoring LLC traffic with cmd bytes 0x%2x%2x\n", (unsigned int) pkt [16], (unsigned int) pkt [17]);
        }
        if (ack) {
                memcpy (llc_ua +  0, peer_mac, 6);
@@ -204,16 +204,13 @@ void onlinetest_top_main (void) {
                        netinputlen = sizeof (netinput);
                        if (bottom_network_recv (netinput, &netinputlen)) {
                                if (memcmp (netinput, "\xff\xff\xff\xff\xff\xff", 6) == 0) {
-                                       bottom_printf ("Broadcast!\n");
-#if 0
-                                       bottom_printf ("Broadcast from %x:%x:%x:%x:%x:%x\n",
+                                       bottom_printf ("Broadcast from %2x:%2x:%2x:%2x:%2x:%2x\n",
                                                        (unsigned int) netinput [ 6],
                                                        (unsigned int) netinput [ 7],
                                                        (unsigned int) netinput [ 8],
                                                        (unsigned int) netinput [ 9],
                                                        (unsigned int) netinput [10],
                                                        (unsigned int) netinput [11]);
-#endif
                                } else {
                                        bottom_led_set (LED_IDX_BACKLIGHT, LED_STABLE_OFF);
                                        selfish_llc2_handler (netinput, netinputlen);
index 7aa6f76..6104392 100644 (file)
@@ -42,7 +42,7 @@
 
 static char consbuf [CONSBUFLEN];
 
-static uint16_t rpos = CONSBUFLEN, wpos = 0;
+static uint16_t rpos = 0, wpos = 0;
 
 
 /******** NETWORK INTERFACE ROUTINES ********/
@@ -94,67 +94,104 @@ void netcons_close (void) {
 static const char digits [] = "0123456789abcdef";
 
 static void cons_putchar (char c) {
-       // TODO: Handle buffer full conditions
        if (wpos >= CONSBUFLEN) {
                wpos = 0;
        }
+       if (wpos + 1 == rpos) {
+               rpos++;
+               if (rpos >= CONSBUFLEN) {
+                       rpos -= CONSBUFLEN;
+               }
+       }
        consbuf [wpos++] = c;
 }
 
-static void cons_putint (uint32_t val, uint8_t base, uint8_t minpos) {
-       uint32_t divisor = 1;
-       while (minpos-- > 0) {
+static void cons_putint (unsigned long int val, uint8_t base, uint8_t minpos) {
+       unsigned long int divisor = 1;
+       while (minpos-- > 1) {
                divisor *= base;
        }
        while (val / base > divisor) {
                divisor *= base;
        }
-       while (divisor > 0) {
+       do {
                cons_putchar (digits [(val / divisor)]);
                val %= divisor;
                divisor /= base;
-       }
+       } while (divisor > 0);
 }
 
 void bottom_console_vprintf (char *fmt, va_list argh) {
        char *fp = fmt;
        char *str;
        char ch;
-       uint32_t intval;
+       unsigned long int intval;
        while (*fp) {
+               uint8_t minpos = 0;
+               bool longval = false;
                if (*fp != '%') {
                        cons_putchar (*fp++);
                } else {
                        fp++;
+               moremeuk:
                        switch (*fp++) {
                        case '\0':
                                fp--;
                                break;
+                       case 'l':
+                               longval = true;
+                               goto moremeuk;
+                       case '0':
+                       case '1':
+                       case '2':
+                       case '3':
+                       case '4':
+                       case '5':
+                       case '6':
+                       case '7':
+                       case '8':
+                       case '9':
+                               minpos *= 10;
+                               minpos += fp [-1] - '0';
+                               goto moremeuk;
                        case 'c':
                                ch = va_arg (argh, char);
                                cons_putchar (ch);
                                break;
                        case 's':
                                str = va_arg (argh, char *);
+                               if (str == NULL) {
+                                       str = "(NULL)";
+                               }
                                while (*str) {
                                        cons_putchar (*str++);
+                                       if (minpos > 0) {
+                                               minpos--;
+                                       }
+                               }
+                               while (minpos-- > 0) {
+                                       cons_putchar (' ');
                                }
                                break;
                        case 'd':
-                               intval = (uint32_t) va_arg (argh, unsigned int);
-                               cons_putint (intval, 10, 0);
-                               break;
-                       case 'l':
-                               intval = va_arg (argh, uint32_t);
-                               cons_putint (intval, 10, 0);
+                               if (longval) {
+                                       intval =                     va_arg (argh, unsigned long int);
+                               } else {
+                                       intval = (unsigned long int) va_arg (argh, unsigned int);
+                               }
+                               cons_putint (intval, 10, minpos);
                                break;
                        case 'p':
-                               intval = (uint32_t) va_arg (argh, void *);
-                               cons_putint (intval, 16, 8);
+                               intval = (unsigned long int) va_arg (argh, void *);
+                               cons_putint (intval, 16, (minpos > 8)? minpos: 8);
                                break;
                        case 'x':
-                               intval = (uint32_t) va_arg (argh, unsigned int);
-                               cons_putint (intval, 16, 8);
+                               if (longval) {
+                                       intval =                     va_arg (argh, unsigned long int);
+                               } else {
+                                       intval = (unsigned long int) va_arg (argh, unsigned int);
+                               }
+                               cons_putint (intval, 16, minpos);
                                break;
                        case '%':
                        default: