Best bringup tool

When I bring up a bare board, I have to fight without OS or libraries, or sometimes even without RAM. Most conservative solution in such case is ICE. But I do not like it because

– ICE is expensive.
– ICE is no use once debug monitor is up.
– ICE is usually hairy and buggy.

I use simple print to the serial I/O console because, to me, the most important information is where the program is and its status. In the boot code, the first thing I do is to initialize the serial I/O, and print at least one character, which shows the board got out of reset and started fetching instructions.

The boot code goes like this:

    #include "mydebug.h"

    // Initialize serial I/O.
    la         t0, SIO_BASE
    li         t1, .....        // baud rate, enable, etc.
    li         t2, .....
    sw         t1, PARAM1(t0)
    sw         t2, PARAM2(t0)

    // Show the first message.
    la         t0, SIO_TXFIFO
    li         t1, 'H'
    sw         t1, (t0)
    li         t1, 'i'
    sw         t1, (t0)
    li         t1, 0x0d
    sw         t1, (t0)
    li         t1, 0x0a
    sw         t1, (t0)

    // Test mydebug functions.
    MYPRINTS("MYPRINTS: Hello world.\r\n")
    MYPRINTS("MYPRINTD: ")
    MYPRINTD(1234567890)
    MYCRLF()
    MYMARKER()

The output looks like this:

    Hi
    MYPRINTS: Hello world.
    MYPRINTD: 1234567890
    [reset.S:32]

The last line is from MYMARKER() macro, which I think most useful.

Once the program jumps to C, I can use a bit better ones.

    #include "mydebug.h"

    int main()
    {
    MYPRINTS("MYPRINTS: Hello from C.\r\n");
    MYPRINTS("MYPRINTD: ")
    MYPRINTD(1234567890)
    MYCRLF()
    MYMARKER()
    }

The output looks like this:

    MYPRINTS: Hello from C.
    MYPRINTD: 1234567890
    [main.c:52 main()]

Here is mydebug.h. Use it at your own risk.

        //
        // For assembler program.
        //
        #ifdef __ASSEMBLER__

        #define MYPRINTC(C)                                             \
                li      t0, SIO_TXFIFO                                  \
                li      t1, C;                                          \
                sw      t1, (t0);                                       \

        #define MYCRLF()                                                \
                MYPRINTC(0x0d);                                         \
                MYPRINTC(0x0a)

        #define MYPRINTS(S)                                             \
                b       1111f;                                          \
                nop;                                                    \
        8888:   .asciz  S;                                              \
                .align  2;                                              \
        1111:   la      t2, 8888b;                                      \
                la      t0, SIO_TXFIFO                                  \
        2222:   lb      t1, (t2);                                       \
                beqz    t1, 9999f;                                      \
                nop;                                                    \
                sw      t1, (t0);                                       \
                addi    t2, 1;                                          \
                b       2222b;                                          \
                nop;                                                    \
        9999:   

        #define MYPRINTD(V)                                             \
                li      t0, SIO_TXFIFO                                  \
                li      t2, V           /* value */;                    \
                li      t3, 1000000000  /* divisor */;                  \
                li      t4, 10;                                         \
                li      t5, 1;          /* leading zero flag */;        \
        1111:   divu    t2, t3;                                         \
                mflo    t1              /* digit */;                    \
                mfhi    t2              /* mod */;                      \
                beqz    t5, 3333f;                                      \
                nop;                                                    \
                beqz    t1, 2222f;                                      \
                nop;                                                    \
                move    t5, zero;                                       \
        3333:   addi    t1, '0';                                        \
                sw      t1, (t0);                                       \
        2222:   divu    t3, t4;                                         \
                mflo    t3;                                             \
                bnez    t3, 1111b;                                      \
                nop

        #define MYMARKER()                                              \
                MYPRINTC('[');                                          \
                MYPRINTS(__FILE__);                                     \
                MYPRINTC(':');                                          \
                MYPRINTD(__LINE__);                                     \
                MYPRINTC(']');                                          \
                MYCRLF()

        //
        // For C program.
        //
        #else // #ifdef __ASSEMBLER__

        #define MYPRINTC(C) {                                                   \
            *(volatile unsigned int*)SIO_TXFIFO = C;                            \
        }
        #define MYPRINTD(V) {                                                   \
            char buf[20];                                                       \
            int n = 0;                                                          \
            unsigned int val = (V);                                             \
            do {                                                                \
                unsigned int digit = val % 10;                                  \
                buf[n++] = '0' + digit;                                         \
                val /= 10;                                                      \
            } while (val);                                                      \
            while (n > 0) MYPRINTC(buf[--n]);                                   \
        }
        #define MYPRINTS(S) {                                                   \
            const char* p = S;                                                  \
            while (*p) MYPRINTC(*p++);                                          \
        }
        #define MYMARKER() {                                                    \
                MYPRINTS("[");                                                  \
                MYPRINTS(__FILE__);                                             \
                MYPRINTS(":");                                                  \
                MYPRINTD(__LINE__);                                             \
                MYPRINTS(" ");                                                  \
                MYPRINTS(__PRETTY_FUNCTION__);                                  \
                MYPRINTS("()]\r\n");                                            \
        }

        #endif // #ifdef __ASSEMBLER__
Advertisements