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