Copyright (c) 2008, Atmel Corporation All rights reserved.
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 RC_calib_oscsampleif.h.
#include <stdint.h>


Go to the source code of this file.
Defines | |
| #define | FAST_RC_NO_SEGMENTS 256 / (1 << FAST_RC_SEGMENT_BIT) |
| Number of segments in Fast RC. | |
| #define | FAST_RC_SEGMENT_BIT 5 |
| FOSCCAL bit deciding range. Used for segment search. | |
| #define | FAST_RC_TARGET_MHZ SYSTEM_CLK_MHz |
| Fast RC target frequency in Hz. Only whole MHz currently allowed. | |
| #define | HOT_TEMPERATURE 85 |
| Production test hot temperature in celcius. | |
| #define | MAX_FAST_RC_ERROR 10 |
| Max error tolerated on Fast RC in ~0,1%, i.e. 10 ~= 1%. | |
| #define | RC_CALIB_CYCLES 8 |
| Number of calibration cycles cycles for OSI calibration. | |
| #define | ROOM_TEMPERATURE 25 |
| Production test room temperature in celcius. | |
| #define | SLOW_RC (1 << OSISEL0) |
| #define | SYSTEM_CLK_MHz 1 |
| System clock frequency in Hz. | |
| #define | T0_PRESCALER T0_PRESCALER_1 |
| #define | T0_PRESCALER_0 0 |
| #define | T0_PRESCALER_1 (1 << CS00) |
| #define | T0_PRESCALER_1024 (1 << CS02) | (1 << CS00) |
| #define | T0_PRESCALER_256 (1 << CS02) |
| #define | T0_PRESCALER_64 (1 << CS01) | (1 << CS00) |
| #define | T0_PRESCALER_8 (1 << CS01) |
| #define | TEMP_DIFF_LIMIT 5 |
| Maximum temperature difference before recalibration. | |
| #define | ULP_RC (0 << OSISEL0) |
| #define | ZERO_C_IN_KELVIN 273 |
| 0 degrees celcius in Kelvin. | |
Functions | |
| uint16_t | CalculateSlowRCperiod (int16_t temperature) |
| Calculate Slow RC period time. | |
| int8_t | CalibrateFastRCruntime (uint16_t cal_RC_period) |
| Calibrate the Fast RC against the Slow RC oscillator runtime. | |
| uint16_t | MeasureULPRCperiod (uint16_t cal_RC_period) |
| Measure the ULP RC period time against the Slow RC. | |
| #define FAST_RC_NO_SEGMENTS 256 / (1 << FAST_RC_SEGMENT_BIT) |
| #define FAST_RC_SEGMENT_BIT 5 |
FOSCCAL bit deciding range. Used for segment search.
Definition at line 75 of file RC_calib_oscsampleif.h.
| #define FAST_RC_TARGET_MHZ SYSTEM_CLK_MHz |
Fast RC target frequency in Hz. Only whole MHz currently allowed.
Definition at line 72 of file RC_calib_oscsampleif.h.
Referenced by CalibrateFastRCruntime().
| #define HOT_TEMPERATURE 85 |
Production test hot temperature in celcius.
Definition at line 55 of file RC_calib_oscsampleif.h.
Referenced by InitBandgap(), and main().
| #define MAX_FAST_RC_ERROR 10 |
Max error tolerated on Fast RC in ~0,1%, i.e. 10 ~= 1%.
Definition at line 77 of file RC_calib_oscsampleif.h.
| #define RC_CALIB_CYCLES 8 |
Number of calibration cycles cycles for OSI calibration.
Definition at line 79 of file RC_calib_oscsampleif.h.
Referenced by OSIsampleClockPeriod().
| #define ROOM_TEMPERATURE 25 |
Production test room temperature in celcius.
Definition at line 54 of file RC_calib_oscsampleif.h.
Referenced by InitBandgap(), and main().
| #define SLOW_RC (1 << OSISEL0) |
Definition at line 81 of file RC_calib_oscsampleif.h.
Referenced by CalibrateFastRCruntime(), and MeasureULPRCperiod().
| #define SYSTEM_CLK_MHz 1 |
System clock frequency in Hz.
System frequency in Hz. Only whole MHz currently allowed.
Definition at line 71 of file RC_calib_oscsampleif.h.
| #define T0_PRESCALER T0_PRESCALER_1 |
| #define T0_PRESCALER_0 0 |
Definition at line 62 of file RC_calib_oscsampleif.h.
| #define T0_PRESCALER_1 (1 << CS00) |
Definition at line 63 of file RC_calib_oscsampleif.h.
| #define T0_PRESCALER_1024 (1 << CS02) | (1 << CS00) |
Definition at line 67 of file RC_calib_oscsampleif.h.
| #define T0_PRESCALER_256 (1 << CS02) |
Definition at line 66 of file RC_calib_oscsampleif.h.
| #define T0_PRESCALER_64 (1 << CS01) | (1 << CS00) |
Definition at line 65 of file RC_calib_oscsampleif.h.
| #define T0_PRESCALER_8 (1 << CS01) |
Definition at line 64 of file RC_calib_oscsampleif.h.
| #define TEMP_DIFF_LIMIT 5 |
Maximum temperature difference before recalibration.
Definition at line 57 of file RC_calib_oscsampleif.h.
Referenced by main().
| #define ULP_RC (0 << OSISEL0) |
| #define ZERO_C_IN_KELVIN 273 |
0 degrees celcius in Kelvin.
Definition at line 53 of file RC_calib_oscsampleif.h.
Referenced by CalculateSlowRCperiod(), and main().
| uint16_t CalculateSlowRCperiod | ( | int16_t | temperature | ) |
Calculate Slow RC period time.
Calculate Slow RC period time given a temperature. The formula for calculation of Slow RC period is used with the signature data (loaded from the signature row) to calculate the actual period as described in the data sheet and application note. The result is in ms * 1024. It can thus be seen as ms in 16 bit fixed point format, with 10 fractional bits, i.e. 0x XXXX XX.xx xxxx xxxx.
| temperature | in Kelvin (uint16_t) |
Definition at line 81 of file RC_calib_oscsampleif.c.
References READ_SIGNATUREBYTE, SIG_SLOW_RC_H, SIG_SLOW_RC_L, SIG_SLOW_RC_PRED_H, SIG_SLOW_RC_PRED_L, SIG_TEMPERATURE_HOT, and ZERO_C_IN_KELVIN.
Referenced by main().
00082 { 00083 uint16_t slow_RC_period; 00084 int16_t slow_RC_temperature_coeff; 00085 uint16_t calib_temperature; 00086 00087 /* Read necessary data from the signature row. The delay cycles are to avoid 00088 * accessing the SPMCSR register within 6 cycles of previous write, since it 00089 * is locked for further writing during these cycles. 00090 */ 00091 slow_RC_period = READ_SIGNATUREBYTE(SIG_SLOW_RC_L); 00092 00093 // Avoid writing to SPMCSR register within 6 cycles of previous write. 00094 __delay_cycles(2); 00095 00096 slow_RC_period |= READ_SIGNATUREBYTE(SIG_SLOW_RC_H) << 8; 00097 00098 // Avoid writing to SPMCSR register within 6 cycles of previous write. 00099 __delay_cycles(2); 00100 00101 slow_RC_temperature_coeff = READ_SIGNATUREBYTE(SIG_SLOW_RC_PRED_L); 00102 00103 // Avoid writing to SPMCSR register within 6 cycles of previous write. 00104 __delay_cycles(2); 00105 00106 slow_RC_temperature_coeff |= READ_SIGNATUREBYTE(SIG_SLOW_RC_PRED_H) << 8; 00107 00108 // Avoid writing to SPMCSR register within 6 cycles of previous write. 00109 __delay_cycles(2); 00110 00111 calib_temperature = READ_SIGNATUREBYTE(SIG_TEMPERATURE_HOT) + ZERO_C_IN_KELVIN; 00112 00113 return (uint16_t)(slow_RC_period - ((temperature - calib_temperature)*slow_RC_temperature_coeff)/64); 00114 }
| int8_t CalibrateFastRCruntime | ( | uint16_t | cal_RC_period | ) |
Calibrate the Fast RC against the Slow RC oscillator runtime.
Since the value we're searching for is probably close to the current, we do a linear search. It searches the segment where FOSCCAL default is and the one below. When searching downwards we use the FOSC SEGMENT signature byte to avoid a jump in frequency when reaching the lower segment and thus giving a longer continous search range. FOSC segment is the first value in the previous segment that gives a lower frequency than the lowest value in the FOSCCAL default segment. If we reach the bottom of the lower segment or the top of the default segment we select the default FOSCCAL value and return failed as this range should provide a more than sufficient range for adjusting FOSCCAL over all temperatures, so something is wrong.
Note that no other boundary check is done, but even if the FOSCCAL value is outside the search range the frequency should be correctly calibrated, although jumps in frequency results will be encountered. If the FOSCCAL value is between the lowest value in FOSCCAL default segment and the FOSC SEGMENT, a value in that range might be selected.
The Oscillator Sampling interface with timer input capture is used in a polled way to minimize interrupt routines.
| cal_RC_period | Slow RC period in ms * 1024 |
Definition at line 143 of file RC_calib_oscsampleif.c.
References FAILED, FAST_RC_TARGET_MHZ, OSIsampleClockPeriod(), READ_SIGNATUREBYTE, SIG_FOSC_SEGMENT, SIG_FOSCCAL_DEFAULT, SLOW_RC, and SUCCESS.
Referenced by main().
00144 { 00145 uint16_t target_period; 00146 int16_t error; 00147 int16_t last_error; 00148 uint8_t fosccal_saved; 00149 00150 /* Read necessary data from the signature row. The delay cycles are to avoid 00151 * accessing the SPMCSR register within 6 cycles of previous write, since it 00152 * is locked for further writing during these cycles. 00153 */ 00154 uint8_t fosccal_default = READ_SIGNATUREBYTE(SIG_FOSCCAL_DEFAULT); 00155 00156 // Avoid writing to SPMCSR register within 6 cycles of previous write. 00157 __delay_cycles(2); 00158 00159 uint8_t fosccal_segment = READ_SIGNATUREBYTE(SIG_FOSC_SEGMENT); 00160 00161 uint8_t bottom_limit = fosccal_segment & 0xE0; 00162 uint8_t top_limit = (fosccal_default & 0xE0) + 0x1F; 00163 00164 // Only whole MHz accounted for. 00165 target_period = cal_RC_period * FAST_RC_TARGET_MHZ; 00166 00167 // Initial measurement to determine search direction. 00168 uint8_t check_value; 00169 error = OSIsampleClockPeriod(SLOW_RC) - target_period; 00170 00171 if(error > 0){ 00172 // Search downwards. 00173 check_value = bottom_limit + 0x1F; 00174 do { 00175 last_error = error; 00176 fosccal_saved = FOSCCAL; 00177 if ( FOSCCAL-- == check_value ){ 00178 // Use fosccal segment value to avoid a step in frequency when going to lower segment. 00179 FOSCCAL = fosccal_segment; 00180 } else if (FOSCCAL < bottom_limit){ 00181 // The range have been searched without success, so we select default fosccal value. 00182 FOSCCAL = fosccal_default; 00183 return FAILED; 00184 } 00185 error = OSIsampleClockPeriod(SLOW_RC) - target_period; 00186 } while (error > 0); 00187 }else{ 00188 // Search upwards. 00189 check_value = fosccal_segment + 0x01; 00190 do { 00191 last_error = error; 00192 fosccal_saved = FOSCCAL; 00193 if ( FOSCCAL++ == check_value ){ 00194 // Use fosccal segment value to avoid a step in frequency when going to upper segment. 00195 FOSCCAL = fosccal_default & 0xE0; 00196 } else if ( FOSCCAL > top_limit ){ 00197 // The range have been searched without success, so we select default fosccal value. 00198 FOSCCAL = fosccal_default; 00199 return FAILED; 00200 } 00201 error = OSIsampleClockPeriod(SLOW_RC) - target_period; 00202 }while ( error < 0 ); 00203 } 00204 00205 /* Neighbor check. Since we're just searching until frequency is too low or 00206 * too high a neighbor check is needed to get the best value. Not needed if 00207 * ~2% accuracy is sufficient. Saves ~60 bytes code in release version if omitted. 00208 */ 00209 if(error < 0){ 00210 // Oscillator frequency to low? If so check if last error was smaller (in absolute value). 00211 if (last_error < -error){ 00212 FOSCCAL = fosccal_saved; 00213 } 00214 }else{ 00215 // Oscillator frequency is to high, so test next lower FOSCCAL setting. 00216 if (-last_error < error){ 00217 FOSCCAL = fosccal_saved; 00218 } 00219 } 00220 00221 return SUCCESS; 00222 }

| uint16_t MeasureULPRCperiod | ( | uint16_t | cal_RC_period | ) |
Measure the ULP RC period time against the Slow RC.
The period of the ULP RC is measured with the Slow RC as reference using the Oscillator Sampling interface. Result is in ms * 1024. It can thus be seen as 16 bit fixed point format, with 10 fractional bits, i.e. 0x XXXX XX.xx xxxx xxxx
| cal_RC_period | (uint16_t) |
Definition at line 236 of file RC_calib_oscsampleif.c.
References OSIsampleClockPeriod(), SLOW_RC, and ULP_RC.
Referenced by main().
00237 { 00238 uint16_t slow_RC_measurement, ULP_RC_measurement; 00239 uint32_t result; 00240 00241 slow_RC_measurement = OSIsampleClockPeriod(SLOW_RC); 00242 ULP_RC_measurement = OSIsampleClockPeriod(ULP_RC); 00243 00244 result = (uint32_t)cal_RC_period * ULP_RC_measurement / slow_RC_measurement; 00245 return (uint16_t)result; 00246 }

1.5.5