kdebug_avr.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_ATMEGA168 || CPU_AVR_ATMEGA328P
00076         #define UCR UCSR0B
00077         #define UDR UDR0
00078         #define USR UCSR0A
00079     #elif CPU_AVR_ATMEGA8 || CPU_AVR_ATMEGA32
00080         #define UCR    UCSRB
00081         #define USR    UCSRA
00082         #define TXEN0  TXEN
00083         #define UDRE0  UDRE
00084         #define TXC0   TXC
00085         #define TXCIE0 TXCIE
00086         #define UDRIE0 UDRIE
00087     #else
00088         #error Unknown CPU
00089     #endif
00090 
00091     #define KDBG_WAIT_READY()     do { loop_until_bit_is_set(USR, UDRE0); } while(0)
00092     #define KDBG_WAIT_TXDONE()    do { loop_until_bit_is_set(USR, TXC0); } while(0)
00093 
00094     /*
00095      * We must clear the TXC flag before sending a new character to allow
00096      * KDBG_WAIT_TXDONE() to work properly.
00097      *
00098      * BUG: if KDBG_WRITE_CHAR() is called after the TXC flag is set by hardware,
00099      * a new TXC could be generated after we've cleared it and before the new
00100      * character is written to UDR.  On a 485 bus, the transceiver will be put
00101      * in RX mode while still transmitting the last char.
00102      */
00103     #define KDBG_WRITE_CHAR(c)    do { USR |= BV(TXC0); UDR = (c); } while(0)
00104 
00105     #define KDBG_MASK_IRQ(old)    do { \
00106         (old) = UCR; \
00107         UCR |= BV(TXEN0); \
00108         UCR &= ~(BV(TXCIE0) | BV(UDRIE0)); \
00109         KDBG_UART0_BUS_TX; \
00110     } while(0)
00111 
00112     #define KDBG_RESTORE_IRQ(old) do { \
00113         KDBG_WAIT_TXDONE(); \
00114         KDBG_UART0_BUS_RX; \
00115         UCR = (old); \
00116     } while(0)
00117 
00118     typedef uint8_t kdbg_irqsave_t;
00119 
00120 #elif CONFIG_KDEBUG_PORT == 1
00121 
00122     /*
00123         * Support for special bus policies or external transceivers
00124         * on UART1 (to be overridden in "hw/hw_ser.h").
00125         *
00126         * HACK: if we don't set TXEN, kdbg disables the transmitter
00127         * after each output statement until the serial driver
00128         * is initialized.  These glitches confuse the debug
00129         * terminal that ends up printing some trash.
00130         */
00131     #ifndef KDBG_UART1_BUS_INIT
00132     #define KDBG_UART1_BUS_INIT  do { \
00133             UCSR1B = BV(TXEN1); \
00134         } while (0)
00135     #endif
00136     #ifndef KDBG_UART1_BUS_RX
00137     #define KDBG_UART1_BUS_RX    do {} while (0)
00138     #endif
00139     #ifndef KDBG_UART1_BUS_TX
00140     #define KDBG_UART1_BUS_TX    do {} while (0)
00141     #endif
00142 
00143     #define KDBG_WAIT_READY()     do { loop_until_bit_is_set(UCSR1A, UDRE1); } while(0)
00144     #define KDBG_WAIT_TXDONE()    do { loop_until_bit_is_set(UCSR1A, TXC1); } while(0)
00145     #define KDBG_WRITE_CHAR(c)    do { UCSR1A |= BV(TXC1); UDR1 = (c); } while(0)
00146 
00147     #define KDBG_MASK_IRQ(old)    do { \
00148         (old) = UCSR1B; \
00149         UCSR1B |= BV(TXEN1); \
00150         UCSR1B &= ~(BV(TXCIE1) | BV(UDRIE1)); \
00151         KDBG_UART1_BUS_TX; \
00152     } while(0)
00153 
00154     #define KDBG_RESTORE_IRQ(old) do { \
00155         KDBG_WAIT_TXDONE(); \
00156         KDBG_UART1_BUS_RX; \
00157         UCSR1B = (old); \
00158     } while(0)
00159 
00160     typedef uint8_t kdbg_irqsave_t;
00161 
00162 /*
00163  * Special debug port for BitBanged Serial see below for details...
00164  */
00165 #elif CONFIG_KDEBUG_PORT == 666
00166     #include "hw/hw_ser.h"
00167     #define KDBG_WAIT_READY()      do { /*nop*/ } while(0)
00168     #define KDBG_WRITE_CHAR(c)     _kdebug_bitbang_putchar((c))
00169     #define KDBG_MASK_IRQ(old)     do { IRQ_SAVE_DISABLE((old)); } while(0)
00170     #define KDBG_RESTORE_IRQ(old)  do { IRQ_RESTORE((old)); } while(0)
00171     typedef cpu_flags_t kdbg_irqsave_t;
00172 
00173     #define KDBG_DELAY (((CPU_FREQ + CONFIG_KDEBUG_BAUDRATE / 2) / CONFIG_KDEBUG_BAUDRATE) + 7) / 14
00174 
00175     static void _kdebug_bitbang_delay(void)
00176     {
00177         unsigned long i;
00178 
00179         for (i = 0; i < KDBG_DELAY; i++)
00180         {
00181             NOP;
00182             NOP;
00183             NOP;
00184             NOP;
00185             NOP;
00186         }
00187     }
00188 
00198     static void _kdebug_bitbang_putchar(char c)
00199     {
00200         int i;
00201         uint16_t data = c;
00202 
00203         /* Add stop bit */
00204         data |= 0x0100;
00205 
00206         /* Add start bit*/
00207         data <<= 1;
00208 
00209         /* Shift out data */
00210         uint16_t shift = 1;
00211         for (i = 0; i < 10; i++)
00212         {
00213             if (data & shift)
00214                 SER_BITBANG_HIGH;
00215             else
00216                 SER_BITBANG_LOW;
00217             _kdebug_bitbang_delay();
00218             shift <<= 1;
00219         }
00220     }
00221 #else
00222     #error CONFIG_KDEBUG_PORT should be either 0, 1 or 666
00223 #endif
00224 
00225 
00226 INLINE void kdbg_hw_init(void)
00227 {
00228     #if CONFIG_KDEBUG_PORT == 666
00229         SER_BITBANG_INIT;
00230     #else /* CONFIG_KDEBUG_PORT != 666 */
00231         /* Compute the baud rate */
00232         uint16_t period = DIV_ROUND(CPU_FREQ / 16UL, CONFIG_KDEBUG_BAUDRATE) - 1;
00233 
00234         #if (CPU_AVR_ATMEGA64 || CPU_AVR_ATMEGA128 || CPU_AVR_ATMEGA1281)
00235             #if CONFIG_KDEBUG_PORT == 0
00236                 UBRR0H = (uint8_t)(period>>8);
00237                 UBRR0L = (uint8_t)period;
00238                 KDBG_UART0_BUS_INIT;
00239             #elif CONFIG_KDEBUG_PORT == 1
00240                 UBRR1H = (uint8_t)(period>>8);
00241                 UBRR1L = (uint8_t)period;
00242                 KDBG_UART1_BUS_INIT;
00243             #else
00244                 #error CONFIG_KDEBUG_PORT must be either 0 or 1
00245             #endif
00246 
00247         #elif CPU_AVR_ATMEGA168 || CPU_AVR_ATMEGA328P
00248             #if CONFIG_KDEBUG_PORT == 0
00249                 UBRR0H = (uint8_t)(period>>8);
00250                 UBRR0L = (uint8_t)period;
00251                 KDBG_UART0_BUS_INIT;
00252             #else
00253                 #error Only CONFIG_KDEBUG_PORT 0 is supported for this cpu
00254             #endif
00255 
00256         #elif CPU_AVR_ATMEGA8 || CPU_AVR_ATMEGA32
00257             #if CONFIG_KDEBUG_PORT == 0
00258                 UBRRH = (uint8_t)(period>>8);
00259                 UBRRL = (uint8_t)period;
00260                 KDBG_UART0_BUS_INIT;
00261             #else
00262                 #error Only CONFIG_KDEBUG_PORT 0 is supported for this cpu
00263             #endif
00264         #elif CPU_AVR_ATMEGA103
00265             #if CONFIG_KDEBUG_PORT == 0
00266                 UBRR = (uint8_t)period;
00267                 KDBG_UART0_BUS_INIT;
00268             #else
00269                 #error Only CONFIG_KDEBUG_PORT 0 is supported for this cpu
00270             #endif
00271         #else
00272             #error Unknown CPU
00273         #endif
00274     #endif /* CONFIG_KDEBUG_PORT == 666 */
00275 }
00276