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