kdebug_xmega.c

Go to the documentation of this file.
00001 
00045 #include <hw/hw_cpufreq.h>  /* for CPU_FREQ */
00046 #include "hw/hw_ser.h"      /* Required for bus macros overrides */
00047 
00048 #include "cfg/cfg_debug.h"  /* for debugging configuration settings */
00049 #include <cfg/macros.h>     /* for BV(), DIV_ROUND */
00050 
00051 #include <cpu/types.h>
00052 #include <cpu/attr.h>
00053 
00054 #include <avr/io.h>
00055 
00056 /* Set KDBG_USART, KDBG_USART_PORT and KDBG_USART_TX_PIN_bm
00057  * according to the CONFIG_KDEBUG_PORT setting
00058  * The Xmega A and D families support at least 2 UARTS
00059  */
00060 #if CONFIG_KDEBUG_PORT == 0
00061     #define KDBG_USART              USARTC0
00062     #define KDBG_USART_PORT         PORTC
00063     #define KDBG_USART_TX_PIN_bm    PIN3_bm
00064 #elif CONFIG_KDEBUG_PORT == 1
00065     #define KDBG_USART              USARTD0
00066     #define KDBG_USART_PORT         PORTD
00067     #define KDBG_USART_TX_PIN_bm    PIN3_bm
00068 #endif
00069 /* Allow the configuration of the extra 3 UARTS for the
00070  * Xmega A family
00071  */
00072 #ifdef CPU_AVR_XMEGA_A
00073     #if CONFIG_KDEBUG_PORT == 2
00074         #define KDBG_USART              USARTC1
00075         #define KDBG_USART_PORT         PORTC
00076         #define KDBG_USART_TX_PIN_bm    PIN7_bm
00077     #elif CONFIG_KDEBUG_PORT == 3
00078         #define KDBG_USART              USARTD1
00079         #define KDBG_USART_PORT         PORTD
00080         #define KDBG_USART_TX_PIN_bm    PIN7_bm
00081     #elif CONFIG_KDEBUG_PORT == 4
00082         #define KDBG_USART              USARTE0
00083         #define KDBG_USART_PORT         PORTE
00084         #define KDBG_USART_TX_PIN_bm    PIN3_bm
00085     #endif
00086 #endif
00087 /* Check if all required KDBG_ macros are defined
00088  */
00089 #ifndef KDBG_USART
00090     #if CPU_AVR_XMEGA_D
00091         #error CONFIG_KDEBUG_PORT should be either 0 or 1
00092     #elif CPU_AVR_XMEGA_A
00093         #error CONFIG_KDEBUG_PORT should be either 0, 1, 2, 3 or 4
00094     #endif
00095 #endif
00096 
00097 /*
00098  * Scalefactor to use for computing the baudrate
00099  * this scalefactor should be an integer value between -7
00100  * and 7
00101  */
00102 #ifndef KDBG_USART_SCALE_FACTOR
00103     #define KDBG_USART_SCALE_FACTOR (-7)
00104 #else
00105     #if KDBG_USART_SCALE_FACTOR > 7 || KDBG_USART_SCALE_FACTOR < -7
00106         #error KDBG_USART_SCALE_FACTOR should be an integer between -7 and 7
00107     #endif
00108 #endif
00109 
00110 /*
00111  * \name KDBG macros
00112  *
00113  * Used to set or alter the KDB_USART operation,
00114  * enable the usart or send a byte.
00115  * Some of these methods are called/included from kdbg_hw_init()
00116  * others are called/included from the cpu independ kdebug implementation
00117  * These macros are heavily imspired by the examples provided by atmel
00118  *
00119  * \{
00120  */
00121 #define KDBG_SET_FORMAT(_charSize, _parityMode, _twoStopBits)         \
00122     (KDBG_USART).CTRLC = (uint8_t) _charSize | _parityMode |                      \
00123                       (_twoStopBits ? USART_SBMODE_bm : 0)
00124 
00125 #define KDBG_SET_BAUDRATE(_bselValue, _bScaleFactor)                  \
00126     (KDBG_USART).BAUDCTRLA =(uint8_t)_bselValue;                                           \
00127     (KDBG_USART).BAUDCTRLB =(_bScaleFactor << USART_BSCALE0_bp)|(_bselValue >> 8)
00128 
00129 #define KDBG_TX_ENABLE()    ((KDBG_USART).CTRLB |= USART_TXEN_bm)
00130 
00131 #define KDBG_SET_MODE(_usartMode)                                      \
00132     ((KDBG_USART).CTRLC = ((KDBG_USART).CTRLC & (~USART_CMODE_gm)) | _usartMode)
00133 
00134 #define KDBG_WAIT_READY()   do{ loop_until_bit_is_set((KDBG_USART).STATUS, USART_DREIF_bp); } while(0)
00135 #define KDBG_WAIT_TXDONE()  do { loop_until_bit_is_set((KDBG_USART).STATUS, USART_TXCIF_bp); } while(0)
00136 #define KDBG_WRITE_CHAR(c)  do { (KDBG_USART).DATA = (c); } while(0)
00137 
00138 #define KDBG_SET_TX_INTERRUPTLEVEL(_txdIntLevel)                      \
00139     (KDBG_USART).CTRLA = ((KDBG_USART).CTRLA & ~USART_TXCINTLVL_gm) | _txdIntLevel
00140 
00141 #define KDBG_SET_DRE_INTERRUPTLEVEL(_dreIntLevel)                      \
00142     (KDBG_USART).CTRLA = ((KDBG_USART).CTRLA & ~USART_DREINTLVL_gm) | _dreIntLevel
00143 
00144 /*\}*/
00145 
00146 /*
00147  * To restore the USART state, to registers need to be restored
00148  * These registers (CTRLA and CTRLB) can be saved to the
00149  * kdbg_avr_xmaga_irqsave structure
00150  */
00151 struct kdbg_avr_xmega_irqsave
00152 {
00153     uint8_t ctrlb;
00154     uint8_t ctrla;
00155 };
00156 typedef struct kdbg_avr_xmega_irqsave kdbg_irqsave_t;
00157 
00158 /*
00159  * param is the kdbg_irqsave_t structure
00160  *
00161  * * Stores the current state of the USART.CTRLA and
00162  * the USART.CTRLB registers
00163  * * Disables Transmit Complete and Date Register Empty interrupts
00164  * * Enabled the transmitter
00165  */
00166 #define KDBG_MASK_IRQ(old)    do { \
00167     (old).ctrlb = KDBG_USART.CTRLB; \
00168     (old).ctrla = KDBG_USART.CTRLA; \
00169     KDBG_SET_TX_INTERRUPTLEVEL(USART_TXCINTLVL_OFF_gc); \
00170     KDBG_SET_DRE_INTERRUPTLEVEL(USART_DREINTLVL_OFF_gc); \
00171     KDBG_TX_ENABLE(); \
00172 } while(0)
00173 
00174 /*
00175  * param is the kdbg_irqsave_t structure
00176  *
00177  * * waits until all data has been transmitted
00178  * * restores the USART.CTRLA and USART.CTRLB registers
00179  */
00180 #define KDBG_RESTORE_IRQ(old) do { \
00181     KDBG_WAIT_TXDONE(); \
00182     KDBG_USART.CTRLB = (old).ctrlb; \
00183     KDBG_USART.CTRLA = (old).ctrla; \
00184 } while(0)
00185 
00186 
00187 /*
00188  * method included from the cpu independent kdebug.c file.
00189  * it initializes KDBG_USART by:
00190  * * Setting the KDBG_USART_TX_PIN_bm as an outputpin
00191  * * Setting KDBG_USART to use 8 bits, No parity, 1 stopbit
00192  * * Setting the baudrate to 115200
00193  * * Enabeling the transmitter
00194  */
00195 INLINE void kdbg_hw_init(void)
00196 {
00197         //set transmit pin as output
00198         KDBG_USART_PORT.OUT = KDBG_USART_PORT.OUT & ~KDBG_USART_TX_PIN_bm;
00199         KDBG_USART_PORT.DIRSET = KDBG_USART_TX_PIN_bm;
00200         //set 8 bits, no parity, 1 stop bit
00201         KDBG_SET_FORMAT(USART_CHSIZE_8BIT_gc, USART_PMODE_DISABLED_gc, false);
00202         //compute and set the baud rate
00203         /* Compute baud-rate period, this requires a valid USART_SCALE_FACTOR */
00204         #if KDBG_USART_SCALE_FACTOR < 0
00205             uint16_t bsel = DIV_ROUND((1 << (-(KDBG_USART_SCALE_FACTOR))) * (CPU_FREQ - (16 * CONFIG_KDEBUG_BAUDRATE)), 16 * CONFIG_KDEBUG_BAUDRATE);
00206         #else
00207             uint16_t bsel = DIV_ROUND(CPU_FREQ, (1 << (KDBG_USART_SCALE_FACTOR)) * 16 * CONFIG_KDEBUG_BAUDRATE) - 1;
00208         #endif
00209         KDBG_SET_BAUDRATE(bsel, KDBG_USART_SCALE_FACTOR);
00210         //enable the Transmitter
00211         KDBG_TX_ENABLE();
00212 }