kdebug_mega.c
Go to the documentation of this file.
00001
00041 #include <hw/hw_cpufreq.h>     /* for CPU_FREQ */
00042 #include "hw/hw_ser.h"     /* Required for bus macros overrides */
00043
00044 #include "cfg/cfg_debug.h"
00045 #include <cfg/macros.h> /* for BV(), DIV_ROUND */
00046
00047 #include <cpu/types.h>
00048 #include <cpu/attr.h>
00049
00050 #include <avr/io.h>
00051
00052 #if CONFIG_KDEBUG_PORT == 0
00053 
00054     /*
00055      * Support for special bus policies or external transceivers
00056      * on UART0 (to be overridden in "hw/hw_ser.h").
00057      *
00058      * HACK: if we don't set TXEN, kdbg disables the transmitter
00059      * after each output statement until the serial driver
00060      * is initialized.  These glitches confuse the debug
00061      * terminal that ends up printing some trash.
00062      */
00063     #ifndef KDBG_UART0_BUS_INIT
00064     #define KDBG_UART0_BUS_INIT  do { \
00065             UCR = BV(TXEN0); \
00066         } while (0)
00067     #endif
00068     #ifndef KDBG_UART0_BUS_RX
00069     #define KDBG_UART0_BUS_RX    do {} while (0)
00070     #endif
00071     #ifndef KDBG_UART0_BUS_TX
00072     #define KDBG_UART0_BUS_TX    do {} while (0)
00073     #endif
00074 
00075     #if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA1281 || CPU_AVR_ATMEGA1280 \
00076         || CPU_AVR_ATMEGA324P || CPU_AVR_ATMEGA644P || CPU_AVR_ATMEGA88P || CPU_AVR_ATMEGA168 \
00077         || CPU_AVR_ATMEGA328P || CPU_AVR_ATMEGA2560
00078         #define UCR UCSR0B
00079         #define UDR UDR0
00080         #define USR UCSR0A
00081     #elif CPU_AVR_ATMEGA8 || CPU_AVR_ATMEGA32
00082         #define UCR    UCSRB
00083         #define USR    UCSRA
00084         #define TXEN0  TXEN
00085         #define UDRE0  UDRE
00086         #define TXC0   TXC
00087         #define TXCIE0 TXCIE
00088         #define UDRIE0 UDRIE
00089     #else
00090         #error Unknown CPU
00091     #endif
00092 
00093     #define KDBG_WAIT_READY()     do { loop_until_bit_is_set(USR, UDRE0); } while(0)
00094     #define KDBG_WAIT_TXDONE()    do { loop_until_bit_is_set(USR, TXC0); } while(0)
00095 
00096     /*
00097      * We must clear the TXC flag before sending a new character to allow
00098      * KDBG_WAIT_TXDONE() to work properly.
00099      *
00100      * BUG: if KDBG_WRITE_CHAR() is called after the TXC flag is set by hardware,
00101      * a new TXC could be generated after we've cleared it and before the new
00102      * character is written to UDR.  On a 485 bus, the transceiver will be put
00103      * in RX mode while still transmitting the last char.
00104      */
00105     #define KDBG_WRITE_CHAR(c)    do { USR |= BV(TXC0); UDR = (c); } while(0)
00106 
00107     #define KDBG_MASK_IRQ(old)    do { \
00108         (old) = UCR; \
00109         UCR |= BV(TXEN0); \
00110         UCR &= ~(BV(TXCIE0) | BV(UDRIE0)); \
00111         KDBG_UART0_BUS_TX; \
00112     } while(0)
00113 
00114     #define KDBG_RESTORE_IRQ(old) do { \
00115         KDBG_WAIT_TXDONE(); \
00116         KDBG_UART0_BUS_RX; \
00117         UCR = (old); \
00118     } while(0)
00119 
00120     typedef uint8_t kdbg_irqsave_t;
00121
00122 #elif CONFIG_KDEBUG_PORT == 1
00123 
00124     /*
00125      * Support for special bus policies or external transceivers
00126      * on UART1 (to be overridden in "hw/hw_ser.h").
00127      *
00128      * HACK: if we don't set TXEN, kdbg disables the transmitter
00129      * after each output statement until the serial driver
00130      * is initialized.  These glitches confuse the debug
00131      * terminal that ends up printing some trash.
00132      */
00133     #ifndef KDBG_UART1_BUS_INIT
00134     #define KDBG_UART1_BUS_INIT  do { \
00135             UCSR1B = BV(TXEN1); \
00136         } while (0)
00137     #endif
00138     #ifndef KDBG_UART1_BUS_RX
00139     #define KDBG_UART1_BUS_RX    do {} while (0)
00140     #endif
00141     #ifndef KDBG_UART1_BUS_TX
00142     #define KDBG_UART1_BUS_TX    do {} while (0)
00143     #endif
00144 
00145     #define KDBG_WAIT_READY()     do { loop_until_bit_is_set(UCSR1A, UDRE1); } while(0)
00146     #define KDBG_WAIT_TXDONE()    do { loop_until_bit_is_set(UCSR1A, TXC1); } while(0)
00147     #define KDBG_WRITE_CHAR(c)    do { UCSR1A |= BV(TXC1); UDR1 = (c); } while(0)
00148 
00149     #define KDBG_MASK_IRQ(old)    do { \
00150         (old) = UCSR1B; \
00151         UCSR1B |= BV(TXEN1); \
00152         UCSR1B &= ~(BV(TXCIE1) | BV(UDRIE1)); \
00153         KDBG_UART1_BUS_TX; \
00154     } while(0)
00155 
00156     #define KDBG_RESTORE_IRQ(old) do { \
00157         KDBG_WAIT_TXDONE(); \
00158         KDBG_UART1_BUS_RX; \
00159         UCSR1B = (old); \
00160     } while(0)
00161 
00162     typedef uint8_t kdbg_irqsave_t;
00163
00164 #elif CONFIG_KDEBUG_PORT == 2
00165 
00166     /*
00167      * Support for special bus policies or external transceivers
00168      * on UART2 (to be overridden in "hw/hw_ser.h").
00169      *
00170      * HACK: if we don't set TXEN, kdbg disables the transmitter
00171      * after each output statement until the serial driver
00172      * is initialized.  These glitches confuse the debug
00173      * terminal that ends up printing some trash.
00174      */
00175     #ifndef KDBG_UART2_BUS_INIT
00176     #define KDBG_UART2_BUS_INIT  do { \
00177             UCSR2B = BV(TXEN2); \
00178         } while (0)
00179     #endif
00180     #ifndef KDBG_UART2_BUS_RX
00181     #define KDBG_UART2_BUS_RX    do {} while (0)
00182     #endif
00183     #ifndef KDBG_UART2_BUS_TX
00184     #define KDBG_UART2_BUS_TX    do {} while (0)
00185     #endif
00186 
00187     #define KDBG_WAIT_READY()     do { loop_until_bit_is_set(UCSR2A, UDRE2); } while(0)
00188     #define KDBG_WAIT_TXDONE()    do { loop_until_bit_is_set(UCSR2A, TXC2); } while(0)
00189     #define KDBG_WRITE_CHAR(c)    do { UCSR2A |= BV(TXC2); UDR2 = (c); } while(0)
00190 
00191     #define KDBG_MASK_IRQ(old)    do { \
00192         (old) = UCSR2B; \
00193         UCSR2B |= BV(TXEN2); \
00194         UCSR2B &= ~(BV(TXCIE2) | BV(UDRIE2)); \
00195         KDBG_UART2_BUS_TX; \
00196     } while(0)
00197 
00198     #define KDBG_RESTORE_IRQ(old) do { \
00199         KDBG_WAIT_TXDONE(); \
00200         KDBG_UART2_BUS_RX; \
00201         UCSR2B = (old); \
00202     } while(0)
00203 
00204     typedef uint8_t kdbg_irqsave_t;
00205
00206 #elif CONFIG_KDEBUG_PORT == 3
00207 
00208     /*
00209      * Support for special bus policies or external transceivers
00210      * on UART3 (to be overridden in "hw/hw_ser.h").
00211      *
00212      * HACK: if we don't set TXEN, kdbg disables the transmitter
00213      * after each output statement until the serial driver
00214      * is initialized.  These glitches confuse the debug
00215      * terminal that ends up printing some trash.
00216      */
00217     #ifndef KDBG_UART3_BUS_INIT
00218     #define KDBG_UART3_BUS_INIT  do { \
00219             UCSR3B = BV(TXEN3); \
00220         } while (0)
00221     #endif
00222     #ifndef KDBG_UART3_BUS_RX
00223     #define KDBG_UART3_BUS_RX    do {} while (0)
00224     #endif
00225     #ifndef KDBG_UART3_BUS_TX
00226     #define KDBG_UART3_BUS_TX    do {} while (0)
00227     #endif
00228 
00229     #define KDBG_WAIT_READY()     do { loop_until_bit_is_set(UCSR3A, UDRE3); } while(0)
00230     #define KDBG_WAIT_TXDONE()    do { loop_until_bit_is_set(UCSR3A, TXC3); } while(0)
00231     #define KDBG_WRITE_CHAR(c)    do { UCSR3A |= BV(TXC3); UDR3 = (c); } while(0)
00232 
00233     #define KDBG_MASK_IRQ(old)    do { \
00234         (old) = UCSR3B; \
00235         UCSR3B |= BV(TXEN3); \
00236         UCSR3B &= ~(BV(TXCIE3) | BV(UDRIE3)); \
00237         KDBG_UART3_BUS_TX; \
00238     } while(0)
00239 
00240     #define KDBG_RESTORE_IRQ(old) do { \
00241         KDBG_WAIT_TXDONE(); \
00242         KDBG_UART3_BUS_RX; \
00243         UCSR3B = (old); \
00244     } while(0)
00245 
00246     typedef uint8_t kdbg_irqsave_t;
00247
00248
00249 /*
00250  * Special debug port for BitBanged Serial see below for details...
00251  */
00252 #elif CONFIG_KDEBUG_PORT == 666
00253     #include "hw/hw_ser.h"
00254     #define KDBG_WAIT_READY()      do { /*nop*/ } while(0)
00255     #define KDBG_WRITE_CHAR(c)     _kdebug_bitbang_putchar((c))
00256     #define KDBG_MASK_IRQ(old)     do { IRQ_SAVE_DISABLE((old)); } while(0)
00257     #define KDBG_RESTORE_IRQ(old)  do { IRQ_RESTORE((old)); } while(0)
00258     typedef cpu_flags_t kdbg_irqsave_t;
00259
00260     #define KDBG_DELAY (((CPU_FREQ + CONFIG_KDEBUG_BAUDRATE / 2) / CONFIG_KDEBUG_BAUDRATE) + 7) / 14
00261 
00262     static void _kdebug_bitbang_delay(void)
00263     {
00264         unsigned long i;
00265
00266         for (i = 0; i < KDBG_DELAY; i++)
00267         {
00268             NOP;
00269             NOP;
00270             NOP;
00271             NOP;
00272             NOP;
00273         }
00274     }
00275
00285     static void _kdebug_bitbang_putchar(char c)
00286     {
00287         int i;
00288         uint16_t data = c;
00289
00290         /* Add stop bit */
00291         data |= 0x0100;
00292
00293         /* Add start bit*/
00294         data <<= 1;
00295
00296         /* Shift out data */
00297         uint16_t shift = 1;
00298         for (i = 0; i < 10; i++)
00299         {
00300             if (data & shift)
00301                 SER_BITBANG_HIGH;
00302             else
00303                 SER_BITBANG_LOW;
00304             _kdebug_bitbang_delay();
00305             shift <<= 1;
00306         }
00307     }
00308 #else
00309     #error CONFIG_KDEBUG_PORT should be either 0, 1, 2, 3 or 666
00310 #endif
00311 
00312
00313 INLINE void kdbg_hw_init(void)
00314 {
00315     #if CONFIG_KDEBUG_PORT == 666
00316         SER_BITBANG_INIT;
00317     #else /* CONFIG_KDEBUG_PORT != 666 */
00318         /* Compute the baud rate */
00319         uint16_t period = DIV_ROUND(CPU_FREQ / 16UL, CONFIG_KDEBUG_BAUDRATE) - 1;
00320
00321         #if (CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA1281 \
00322             || CPU_AVR_ATMEGA324P || CPU_AVR_ATMEGA644P)
00323             #if CONFIG_KDEBUG_PORT == 0
00324                 UBRR0H = (uint8_t)(period>>8);
00325                 UBRR0L = (uint8_t)period;
00326                 KDBG_UART0_BUS_INIT;
00327             #elif CONFIG_KDEBUG_PORT == 1
00328                 UBRR1H = (uint8_t)(period>>8);
00329                 UBRR1L = (uint8_t)period;
00330                 KDBG_UART1_BUS_INIT;
00331             #else
00332                 #error CONFIG_KDEBUG_PORT must be either 0 or 1
00333             #endif
00334 
00335         #elif CPU_AVR_ATMEGA1280 || CPU_AVR_ATMEGA2560
00336             #if CONFIG_KDEBUG_PORT == 0
00337                 UBRR0H = (uint8_t)(period>>8);
00338                 UBRR0L = (uint8_t)period;
00339                 KDBG_UART0_BUS_INIT;
00340             #elif CONFIG_KDEBUG_PORT == 1
00341                 UBRR1H = (uint8_t)(period>>8);
00342                 UBRR1L = (uint8_t)period;
00343                 KDBG_UART1_BUS_INIT;
00344             #elif CONFIG_KDEBUG_PORT == 2
00345                 UBRR2H = (uint8_t)(period>>8);
00346                 UBRR2L = (uint8_t)period;
00347                 KDBG_UART2_BUS_INIT;
00348             #elif CONFIG_KDEBUG_PORT == 3
00349                 UBRR3H = (uint8_t)(period>>8);
00350                 UBRR3L = (uint8_t)period;
00351                 KDBG_UART3_BUS_INIT;
00352             #else
00353                 #error CONFIG_KDEBUG_PORT must be either 0 or 1 or 2 or 3
00354             #endif
00355 
00356         #elif CPU_AVR_ATMEGA88P || CPU_AVR_ATMEGA168 || CPU_AVR_ATMEGA328P
00357             #if CONFIG_KDEBUG_PORT == 0
00358                 UBRR0H = (uint8_t)(period>>8);
00359                 UBRR0L = (uint8_t)period;
00360                 UCSR0A = 0; /* The Arduino Uno bootloader turns on U2X0 */
00361                 KDBG_UART0_BUS_INIT;
00362             #else
00363                 #error Only CONFIG_KDEBUG_PORT 0 is supported for this cpu
00364             #endif
00365 
00366         #elif CPU_AVR_ATMEGA8 || CPU_AVR_ATMEGA32
00367             #if CONFIG_KDEBUG_PORT == 0
00368                 UBRRH = (uint8_t)(period>>8);
00369                 UBRRL = (uint8_t)period;
00370                 KDBG_UART0_BUS_INIT;
00371             #else
00372                 #error Only CONFIG_KDEBUG_PORT 0 is supported for this cpu
00373             #endif
00374         #elif CPU_AVR_ATMEGA103
00375             #if CONFIG_KDEBUG_PORT == 0
00376                 UBRR = (uint8_t)period;
00377                 KDBG_UART0_BUS_INIT;
00378             #else
00379                 #error Only CONFIG_KDEBUG_PORT 0 is supported for this cpu
00380             #endif
00381         #else
00382             #error Unknown CPU
00383         #endif
00384     #endif /* CONFIG_KDEBUG_PORT == 666 */
00385 }
00386