kdebug_avr.c

Go to the documentation of this file.
00001 
00042 #include <cpu/types.h>
00043 #include <cpu/attr.h>
00044 #include <cfg/macros.h> /* for BV(), DIV_ROUND */
00045 #include <appconfig.h>
00046 #include <hw_cpu.h>     /* for CLOCK_FREQ */
00047 #include <hw_ser.h>     /* Required for bus macros overrides */
00048 
00049 #include <avr/io.h>
00050 
00051 #if CONFIG_KDEBUG_PORT == 0
00052 
00053     /*
00054      * Support for special bus policies or external transceivers
00055      * on UART0 (to be overridden in "hw_ser.h").
00056      *
00057      * HACK: if we don't set TXEN, kdbg disables the transmitter
00058      * after each output statement until the serial driver
00059      * is initialized.  These glitches confuse the debug
00060      * terminal that ends up printing some trash.
00061      */
00062     #ifndef KDBG_UART0_BUS_INIT
00063     #define KDBG_UART0_BUS_INIT  do { \
00064             UCSR0B = BV(TXEN0); \
00065         } while (0)
00066     #endif
00067     #ifndef KDBG_UART0_BUS_RX
00068     #define KDBG_UART0_BUS_RX    do {} while (0)
00069     #endif
00070     #ifndef KDBG_UART0_BUS_TX
00071     #define KDBG_UART0_BUS_TX    do {} while (0)
00072     #endif
00073 
00074     #if CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA168
00075         #define UCR UCSR0B
00076         #define UDR UDR0
00077         #define USR UCSR0A
00078     #elif CPU_AVR_ATMEGA8
00079         #define UCR UCSRB
00080         #define USR UCSRA
00081     #else
00082         #error Unknown CPU
00083     #endif
00084 
00085     #define KDBG_WAIT_READY()     do { loop_until_bit_is_set(USR, UDRE0); } while(0)
00086     #define KDBG_WAIT_TXDONE()    do { loop_until_bit_is_set(USR, TXC0); } while(0)
00087 
00088     /*
00089      * We must clear the TXC flag before sending a new character to allow
00090      * KDBG_WAIT_TXDONE() to work properly.
00091      *
00092      * BUG: if KDBG_WRITE_CHAR() is called after the TXC flag is set by hardware,
00093      * a new TXC could be generated after we've cleared it and before the new
00094      * character is written to UDR.  On a 485 bus, the transceiver will be put
00095      * in RX mode while still transmitting the last char.
00096      */
00097     #define KDBG_WRITE_CHAR(c)    do { USR |= BV(TXC0); UDR = (c); } while(0)
00098 
00099     #define KDBG_MASK_IRQ(old)    do { \
00100         (old) = UCR; \
00101         UCR |= BV(TXEN0); \
00102         UCR &= ~(BV(TXCIE0) | BV(UDRIE0)); \
00103         KDBG_UART0_BUS_TX; \
00104     } while(0)
00105 
00106     #define KDBG_RESTORE_IRQ(old) do { \
00107         KDBG_WAIT_TXDONE(); \
00108         KDBG_UART0_BUS_RX; \
00109         UCR = (old); \
00110     } while(0)
00111 
00112     typedef uint8_t kdbg_irqsave_t;
00113 
00114 #elif CONFIG_KDEBUG_PORT == 1
00115 
00116     /*
00117         * Support for special bus policies or external transceivers
00118         * on UART1 (to be overridden in "hw_ser.h").
00119         *
00120         * HACK: if we don't set TXEN, kdbg disables the transmitter
00121         * after each output statement until the serial driver
00122         * is initialized.  These glitches confuse the debug
00123         * terminal that ends up printing some trash.
00124         */
00125     #ifndef KDBG_UART1_BUS_INIT
00126     #define KDBG_UART1_BUS_INIT  do { \
00127             UCSR1B = BV(TXEN1); \
00128         } while (0)
00129     #endif
00130     #ifndef KDBG_UART1_BUS_RX
00131     #define KDBG_UART1_BUS_RX    do {} while (0)
00132     #endif
00133     #ifndef KDBG_UART1_BUS_TX
00134     #define KDBG_UART1_BUS_TX    do {} while (0)
00135     #endif
00136 
00137     #define KDBG_WAIT_READY()     do { loop_until_bit_is_set(UCSR1A, UDRE1); } while(0)
00138     #define KDBG_WAIT_TXDONE()    do { loop_until_bit_is_set(UCSR1A, TXC1); } while(0)
00139     #define KDBG_WRITE_CHAR(c)    do { UCSR1A |= BV(TXC1); UDR1 = (c); } while(0)
00140 
00141     #define KDBG_MASK_IRQ(old)    do { \
00142         (old) = UCSR1B; \
00143         UCSR1B |= BV(TXEN1); \
00144         UCSR1B &= ~(BV(TXCIE1) | BV(UDRIE1)); \
00145         KDBG_UART1_BUS_TX; \
00146     } while(0)
00147 
00148     #define KDBG_RESTORE_IRQ(old) do { \
00149         KDBG_WAIT_TXDONE(); \
00150         KDBG_UART1_BUS_RX; \
00151         UCSR1B = (old); \
00152     } while(0)
00153 
00154     typedef uint8_t kdbg_irqsave_t;
00155 
00156 /*
00157  * Special debug port for BitBanged Serial see below for details...
00158  */
00159 #elif CONFIG_KDEBUG_PORT == 666
00160     #include "hw_ser.h"
00161     #define KDBG_WAIT_READY()      do { /*nop*/ } while(0)
00162     #define KDBG_WRITE_CHAR(c)     _kdebug_bitbang_putchar((c))
00163     #define KDBG_MASK_IRQ(old)     do { IRQ_SAVE_DISABLE((old)); } while(0)
00164     #define KDBG_RESTORE_IRQ(old)  do { IRQ_RESTORE((old)); } while(0)
00165     typedef cpuflags_t kdbg_irqsave_t;
00166 
00167     #define KDBG_DELAY (((CLOCK_FREQ + CONFIG_KDEBUG_BAUDRATE / 2) / CONFIG_KDEBUG_BAUDRATE) + 7) / 14
00168 
00169     static void _kdebug_bitbang_delay(void)
00170     {
00171         unsigned long i;
00172 
00173         for (i = 0; i < KDBG_DELAY; i++)
00174         {
00175             NOP;
00176             NOP;
00177             NOP;
00178             NOP;
00179             NOP;
00180         }
00181     }
00182 
00192     static void _kdebug_bitbang_putchar(char c)
00193     {
00194         int i;
00195         uint16_t data = c;
00196 
00197         /* Add stop bit */
00198         data |= 0x0100;
00199 
00200         /* Add start bit*/
00201         data <<= 1;
00202 
00203         /* Shift out data */
00204         uint16_t shift = 1;
00205         for (i = 0; i < 10; i++)
00206         {
00207             if (data & shift)
00208                 SER_BITBANG_HIGH;
00209             else
00210                 SER_BITBANG_LOW;
00211             _kdebug_bitbang_delay();
00212             shift <<= 1;
00213         }
00214     }
00215 #else
00216     #error CONFIG_KDEBUG_PORT should be either 0, 1 or 666
00217 #endif
00218 
00219 
00220 INLINE void kdbg_hw_init(void)
00221 {
00222     #if CONFIG_KDEBUG_PORT == 666
00223         SER_BITBANG_INIT;
00224     #else /* CONFIG_KDEBUG_PORT != 666 */
00225         /* Compute the baud rate */
00226         uint16_t period = DIV_ROUND(CLOCK_FREQ / 16UL, CONFIG_KDEBUG_BAUDRATE) - 1;
00227 
00228         #if (CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128)
00229             #if CONFIG_KDEBUG_PORT == 0
00230                 UBRR0H = (uint8_t)(period>>8);
00231                 UBRR0L = (uint8_t)period;
00232                 KDBG_UART0_BUS_INIT;
00233             #elif CONFIG_KDEBUG_PORT == 1
00234                 UBRR1H = (uint8_t)(period>>8);
00235                 UBRR1L = (uint8_t)period;
00236                 KDBG_UART1_BUS_INIT;
00237             #else
00238                 #error CONFIG_KDEBUG_PORT must be either 0 or 1
00239             #endif
00240 
00241         #elif CPU_AVR_ATMEGA168
00242             UBRR0H = (uint8_t)(period>>8);
00243             UBRR0L = (uint8_t)period;
00244             KDBG_UART0_BUS_INIT;
00245         #elif CPU_AVR_ATMEGA8
00246             UBRRH = (uint8_t)(period>>8);
00247             UBRRL = (uint8_t)period;
00248         #elif CPU_AVR_ATMEGA103
00249             UBRR = (uint8_t)period;
00250             KDBG_UART0_BUS_INIT;
00251         #else
00252             #error Unknown CPU
00253         #endif
00254     #endif /* CONFIG_KDEBUG_PORT == 666 */
00255 }