This code is capable of calibrating the internal RC oscillator of XMEGA with JTAG interface
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. The name of ATMEL may not be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY ATMEL "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY AND SPECIFICALLY DISCLAIMED. IN NO EVENT SHALL ATMEL BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Definition in file main.c.
#include "avr_compiler.h"
#include "clksys_driver.h"
#include "TC_driver.h"
#include "event_system_driver.h"
#include "eeprom_driver.h"
Go to the source code of this file.
Defines | |
#define | CAL_REF_CLOCK_FREQ (32768) |
#define | CAL_REF_NUM (32000000/32768) |
#define | EEPROM_BYTE_ADDR_2M_1 (0x2) |
#define | EEPROM_BYTE_ADDR_2M_2 (0x3) |
#define | EEPROM_BYTE_ADDR_32k (0x4) |
#define | EEPROM_BYTE_ADDR_32M_1 (0x0) |
#define | EEPROM_BYTE_ADDR_32M_2 (0x1) |
#define | EEPROM_PAGE_ADDR_2M (0x0) |
Address saved 2MHz internal RC oscilaor calibration value. | |
#define | EEPROM_PAGE_ADDR_32k (0x0) |
Address saved 32.768kHz internal RC oscilaor calibration value. | |
#define | EEPROM_PAGE_ADDR_32M (0x0) |
Address saved 32MHz internal RC oscilaor calibration value. | |
#define | Handshake_Cycle (8) |
#define | JTAG_TDI (PIN5_bm) |
#define | JTAG_TDO (PIN7_bm) |
#define | OSC_Stable_Cycle (4032) |
#define | SYS_CLOCK (32000000) |
Typedefs | |
typedef enum cal_status_enum | cal_status_t |
Current frequecy status. | |
Enumerations | |
enum | cal_status_enum { FREQ_ADJ, FREQ_MEASURE } |
Current frequecy status. More... | |
Functions | |
ISR (TCC0_CCA_vect) | |
Timer Counter C0 Compare/Capture A. | |
int | main (void) |
static void | port_init (void) |
Configures the necessary IO lines. | |
static void | TC0_ConfigCapture (volatile TC0_t *tc, TC_EVSEL_t eventSource, TC_EVACT_t eventAction) |
Configures the Timer/Counter 0 for input capture operation. | |
static void | tcc0_init (void) |
Timer initialization. | |
Variables | |
static volatile bool | Calibration_flag = false |
A flag indicates if the calibration suceessed. | |
static volatile uint16_t | cca = 0 |
A counter save frequecy. | |
static volatile bool | flag = false |
A flag indicates if the calibration status finished. | |
static volatile bool | state_change = false |
A flag indicates the frequecy capture status. | |
static uint8_t | step_size = 0x80 |
Binary search step size. |
#define EEPROM_PAGE_ADDR_2M (0x0) |
#define EEPROM_PAGE_ADDR_32k (0x0) |
#define EEPROM_PAGE_ADDR_32M (0x0) |
#define JTAG_TDO (PIN7_bm) |
typedef enum cal_status_enum cal_status_t |
Current frequecy status.
enum cal_status_enum |
Current frequecy status.
Definition at line 80 of file main.c.
00080 { 00081 FREQ_ADJ, 00082 FREQ_MEASURE, 00083 } cal_status_t;
ISR | ( | TCC0_CCA_vect | ) |
Timer Counter C0 Compare/Capture A.
This routine increments compareMatchACount each time it is called.
Definition at line 257 of file main.c.
References cca, and state_change.
00258 { 00259 cca = TCC0.CCA; 00260 state_change = true; 00261 }
int main | ( | void | ) |
Definition at line 117 of file main.c.
References CAL_REF_NUM, Calibration_flag, cca, CCPWrite(), CLKSYS_AutoCalibration_Enable(), CLKSYS_Enable, CLKSYS_IsReady, CLKSYS_Main_ClockSource_Select(), CLKSYS_Prescalers_Config(), EEPROM_BYTE_ADDR_2M_1, EEPROM_BYTE_ADDR_2M_2, EEPROM_BYTE_ADDR_32k, EEPROM_BYTE_ADDR_32M_1, EEPROM_BYTE_ADDR_32M_2, EEPROM_DisableMapping, EEPROM_PAGE_ADDR_2M, EEPROM_PAGE_ADDR_32k, EEPROM_PAGE_ADDR_32M, EEPROM_WriteByte(), flag, FREQ_ADJ, FREQ_MEASURE, Handshake_Cycle, JTAG_TDI, JTAG_TDO, OSC_Stable_Cycle, port_init(), state_change, step_size, and tcc0_init().
00118 { 00119 /* A flag indicate current calibration status. */ 00120 cal_status_t cal_status = FREQ_ADJ; 00121 /* A counter indictate currnt received clock cycle. */ 00122 uint16_t cnt = 0; 00123 00124 uint16_t i; 00125 00126 /* Disable JTAG interface. */ 00127 CCPWrite( &MCU.MCUCR, 1 ); 00128 /* initialize RC32KCAL register. */ 00129 OSC.RC32KCAL = step_size; 00130 00131 /* Enable internal 32 MHz RC oscillator and wait until it's stable. Then set 00132 * the 32 MHz RC oscillator as the main clock source. 00133 */ 00134 CLKSYS_Enable( OSC_RC32MEN_bm | OSC_RC32KEN_bm ); 00135 while ( CLKSYS_IsReady( OSC_RC32KEN_bm ) == 0 ); 00136 CLKSYS_Prescalers_Config( CLK_PSADIV_1_gc, CLK_PSBCDIV_1_1_gc ); 00137 while ( CLKSYS_IsReady( OSC_RC32MRDY_bm ) == 0 ); 00138 CLKSYS_Main_ClockSource_Select( CLK_SCLKSEL_RC32M_gc ); 00139 00140 /* Enable automatic calibration of internal 32 MHz and 2 MHz RC oscillator. */ 00141 CLKSYS_AutoCalibration_Enable( OSC_RC32MCREF_bm, false ); 00142 CLKSYS_AutoCalibration_Enable( OSC_RC2MCREF_bm, false ); 00143 00144 /* Peripheral initialization. */ 00145 tcc0_init(); 00146 port_init(); 00147 /* enable the low level interrupt */ 00148 PMIC.CTRL |= PMIC_LOLVLEX_bm; 00149 sei(); 00150 00151 /* Start binary search. */ 00152 while ( !flag ) { 00153 if (state_change == true) { 00154 state_change = false; 00155 if (cal_status == FREQ_ADJ) { 00156 if( cnt > OSC_Stable_Cycle ) { 00157 cnt = 0; 00158 cal_status = FREQ_MEASURE; 00159 } else { 00160 cnt ++; 00161 } 00162 } else { 00163 if (step_size == 1) { 00164 if ((cca > CAL_REF_NUM*0.99) && (cca <CAL_REF_NUM*1.01)) { 00165 flag = true; 00166 Calibration_flag = true; 00167 00168 } else { 00169 Calibration_flag = false; 00170 flag = true; 00171 } 00172 } else { 00173 step_size = step_size / 2; 00174 if (cca > CAL_REF_NUM) { 00175 OSC.RC32KCAL -= step_size; 00176 } else { 00177 OSC.RC32KCAL += step_size; 00178 } 00179 } 00180 cal_status = FREQ_ADJ; 00181 } 00182 } 00183 } 00184 00185 00186 00187 /* Send Handshanking signle. true output 0x55,false ouput 0x0 */ 00188 if ( Calibration_flag ) 00189 for (i = 0; i < Handshake_Cycle ;i++){ 00190 while (PORTB.IN & JTAG_TDI){ 00191 } 00192 PORTB.OUTTGL |= JTAG_TDO; 00193 while (!(PORTB.IN & JTAG_TDI)){ 00194 } 00195 } 00196 else 00197 for (i = 0; i < Handshake_Cycle ;i++){ 00198 while (PORTB.IN & JTAG_TDI){ 00199 } 00200 PORTB.OUT &= ~JTAG_TDO; 00201 while (!(PORTB.IN & JTAG_TDI)){ 00202 } 00203 } 00204 00205 /* Save calibration value for 32.768 KHz, 2 MHz and 32 MHz*/ 00206 if ( Calibration_flag ){ 00207 00208 EEPROM_DisableMapping(); 00209 00210 EEPROM_WriteByte(EEPROM_PAGE_ADDR_32k, EEPROM_BYTE_ADDR_32k, OSC.RC32KCAL); 00211 00212 EEPROM_WriteByte(EEPROM_PAGE_ADDR_32M, EEPROM_BYTE_ADDR_32M_1, DFLLRC32M.CALA); 00213 EEPROM_WriteByte(EEPROM_PAGE_ADDR_32M, EEPROM_BYTE_ADDR_32M_2, DFLLRC32M.CALB); 00214 00215 EEPROM_WriteByte(EEPROM_PAGE_ADDR_2M, EEPROM_BYTE_ADDR_2M_1, DFLLRC2M.CALA); 00216 EEPROM_WriteByte(EEPROM_PAGE_ADDR_2M, EEPROM_BYTE_ADDR_2M_2, DFLLRC2M.CALB); 00217 } 00218 00219 00220 /* Reenable JTAG interface. */ 00221 CCPWrite( &MCU.MCUCR, 0 ); 00222 00223 while(true){ 00224 } 00225 }
static void port_init | ( | void | ) | [static] |
Configures the necessary IO lines.
Definition at line 236 of file main.c.
References EVSYS_SetEventSource(), and JTAG_TDO.
Referenced by main().
00237 { 00238 PORTB.DIR |= JTAG_TDO; 00239 PORTB.OUT |= JTAG_TDO; 00240 PORTB.PIN7CTRL = (uint8_t) PORT_OPC_PULLUP_gc; 00241 PORTB.PIN5CTRL = (uint8_t) PORT_OPC_PULLUP_gc | PORT_ISC_RISING_gc; 00242 EVSYS_SetEventSource( 0, EVSYS_CHMUX_PORTB_PIN5_gc); 00243 }
static void TC0_ConfigCapture | ( | volatile TC0_t * | tc, | |
TC_EVSEL_t | eventSource, | |||
TC_EVACT_t | eventAction | |||
) | [static] |
Configures the Timer/Counter 0 for input capture operation.
This function sets the Timer/Counter in input capture mode and selects the event lines that will trigger the individual input capture channels.
tc | Timer/Counter module instance. | |
eventSource | Event source selection. |
Definition at line 245 of file main.c.
Referenced by tcc0_init().
00246 { 00247 tc->CTRLD = ( tc->CTRLD & ~( TC0_EVSEL_gm | TC0_EVACT_gm ) ) | 00248 eventSource | 00249 eventAction; 00250 }
static void tcc0_init | ( | void | ) | [static] |
Timer initialization.
Definition at line 227 of file main.c.
References TC0_ConfigCapture(), TC0_ConfigClockSource(), TC0_ConfigWGM(), TC0_EnableCCChannels(), and TC0_SetCCAIntLevel().
Referenced by main().
00228 { 00229 TC0_ConfigWGM( &TCC0, TC_WGMODE_NORMAL_gc); 00230 TC0_EnableCCChannels( &TCC0, TC0_CCAEN_bm); 00231 TC0_ConfigCapture( &TCC0, TC_EVSEL_CH0_gc, TC_EVACT_FRW_gc); 00232 TC0_SetCCAIntLevel( &TCC0, TC_CCAINTLVL_LO_gc); 00233 TC0_ConfigClockSource( &TCC0, TC_CLKSEL_DIV1_gc); 00234 }
volatile bool Calibration_flag = false [static] |
volatile uint16_t cca = 0 [static] |
volatile bool flag = false [static] |
volatile bool state_change = false [static] |
uint8_t step_size = 0x80 [static] |