Detect the crystal used on MCU - Page 1
Forum section: electronics / general

author: technix
author_rank: Super Contributor
timestamp: December 24, 2016, 05:21:35 pm
content: For those microcontrollers that have both internal and external clock sources, as well as allowing switching clock sources, can you detect the crystal connected and set up clocks appropriately? I am talking about detecting which PLL settings I should use, without prior knowledge of the speed of the crystal.I am talking about the following chips:* STM32F103CBT6 (ARM Cortex-M3)* PIC18F4550 (PICmicro Enhanced)* PIC24FV32KA304 (PIC16)* LPC2103F (ARM7TDMI-S)I have a working replacement STM32 PLL setup code that accepts 3/4/6/8/12/16MHz crystals and set up PLL, ADC and USB all appropriately. Currently it is up to the programmer to select which code path to use, but I wish I can add crystal detecting code in there so the developer don't need to specify the actual crystal frequency.

author: daqq
author_rank: Super Contributor
timestamp: December 24, 2016, 05:36:37 pm
content: Most of the STM32 devices have the CSS module - Clock Security System. Essentially, if the external oscillator fails for some reason, an interrupt is generated.I don't know about the rest.

author: technix
author_rank: Super Contributor
timestamp: December 24, 2016, 06:20:50 pm
content: Quote from: daqq on December 24, 2016, 05:36:37 pmThat is not what I am looking into. The first post is edited with clarifications now.

author: JimRemington
author_rank: Regular Contributor
timestamp: December 24, 2016, 07:11:56 pm
content: QuoteSince the crystal can theoretically be any allowed frequency, you would need a separate reference clock to determine the main crystal frequency.The accuracy of that frequency determination would rest entirely on the accuracy of the reference clock, so your quest seems pointless.

author: donotdespisethesnake
author_rank: Super Contributor
timestamp: December 24, 2016, 07:20:38 pm
content: Quote from: technix on December 24, 2016, 05:21:35 pmOf course, if you add suitable external hardware to count the frequency, then you can read the frequency.But adding a frequency counter to your design is probably not you wanted, but you didn't constrain the requirement...Assuming you meant "is there a simple and zero cost way" then the general answer is no.

author: Someone
author_rank: Super Contributor
timestamp: December 24, 2016, 07:39:18 pm
content: Quote from: technix on December 24, 2016, 05:21:35 pmIts not possible to do generically, and in many cases the external crystals need different configurations of the oscillator just to run. If you're wanting a routine to quickly measure what speed the oscillator is currently running at to then bump the PLL its simply a matter of using the RTC (or other timer running from an asynchronous clock) to measure the frequency but again thats very specific to each chip.

author: technix
author_rank: Super Contributor
timestamp: December 24, 2016, 07:46:53 pm
content: Quote from: JimRemington on December 24, 2016, 07:11:56 pmNo. In the example initializing code only crystals of frequency 3, 4, 6, 8, 12 and 16MHz are allowed, else the internal oscillator is still used.

author: ataradov
author_rank: Super Contributor
timestamp: December 24, 2016, 08:10:46 pm
content: Quote from: technix on December 24, 2016, 07:46:53 pmMost MCUs will have low power low frequency (typically around 32 kHz) RC oscillator. You can enable external crystal and count the number of cycles that fits into one cycle of that internal RC.Bootloaders in Atmel SAM MCUs detect the crystal frequency this way.

author: T3sl4co1l
author_rank: Super Contributor
timestamp: December 24, 2016, 08:31:30 pm
content: It would be interesting to tie in an ADC pin, so you pulse one side and watch the ringdown on the other side. It wouldn't be feasible for normal speed ADCs and MHz crystals, but might be possible for low frequency crystals. (But then, who uses anything other than 32.768kHz?)Perhaps cycling through the different oscillator modes, and seeing which ones produce useful output, would be reasonable. That does depend upon the hardware they use to detect it, which might not be consistent, or might not detect the same conditions that one would like for design purposes. For design, one wishes to have it working, with enough margin that it won't stop working at high or low temperature, and will be consistent between chips.Tim

author: Jeroen3
author_rank: Super Contributor
timestamp: December 24, 2016, 11:37:25 pm
content: Well yes you sure can on an STM32F103. Not very accurate, but you can.QuoteAnd you can always perform comparison between RTC on LSE and a TIM on HSI. With some software polling though.

author: JimRemington
author_rank: Regular Contributor
timestamp: December 25, 2016, 02:09:57 am
content: QuoteWhat example?The comment is certainly not relevant to PIC18F4550 or PIC24FV32KA304, as in the OP.

author: technix
author_rank: Super Contributor
timestamp: December 25, 2016, 03:43:45 am
content: Quote from: JimRemington on December 25, 2016, 02:09:57 amOn those other processors there are also a small discrete selection of supported crystal frequencies.

author: JimRemington
author_rank: Regular Contributor
timestamp: December 25, 2016, 04:11:49 am
content: No such restriction on the PIC18F4550. From the data sheet:QuoteBye.

author: technix
author_rank: Super Contributor
timestamp: December 25, 2016, 04:34:37 am
content: Quote from: JimRemington on December 25, 2016, 04:11:49 amNope.I need to detect the frequency of the external crystal to set up PLL appropriately in the first place.

author: donotdespisethesnake
author_rank: Super Contributor
timestamp: December 25, 2016, 10:03:20 am
content: I am assuming that the crystal is fitted at manufacture, and not a user changeable part, because the OP does not specify.We use IO pins to select configurable options that can't be set in EEPROM. 3 pins would give 8 options. Resistors are used to select 0 or 1, if internal pullups are used then fit/no fit.I have found the internal slow clocks too inaccurate to reliably identify external crystals.

author: nctnico
author_rank: Super Contributor
timestamp: December 25, 2016, 01:09:45 pm
content: If you have an internal (RC) oscillator, 32kHz crystal for the RTC or an accurate RC on a pin then it should be possible to do a guestimate. In many cases a microcontroller will have a typical crystal value (like 12MHz on NXP's LPC ARM series) so all in all there shouldn't be that much variation.

author: technix
author_rank: Super Contributor
timestamp: December 25, 2016, 02:37:27 pm
content: Quote from: nctnico on December 25, 2016, 01:09:45 pmStill using the STM32 example, it have a built-in 8MHz RC oscillator but how do I perform this guesstimate?

author: dgtl
author_rank: Regular Contributor
timestamp: December 25, 2016, 07:34:58 pm
content: A lot of STM32 chips have a feature, that LSI 32kHz clock can be redirected to one timer capture input (look for timer remap in RM). You configure your system to run on the unknown xtal without PLL, then start the timer at max rate and let it count the number of clocks in one LSI 32kHz period using this HW capture. As the LSI is not very precise (ie for F1 30..60kHz), you can not distinguish between any XTAL speed, but you can support a list of common values, that are spaced apart wide enough. Also, the PLL settings and the clocks derived from that depend on the exact xtal speed, so you'll need to keep a table of PLL settings and clock dividers to use later on.For more precision or when this feature is not present, you need to use 32kHz crystal. AFAIK STM32-s do not support redirecting LSE 32KHz to timer capture, you can just do it in software - set up RTC timer and measure how fast the code is running within 1sec of RTC change (can be either just number of loops, values from a hw timer, values from ARM Cortex DWT_CYCCNT performance counter etc. ). This will take up to 2sec but is doable on any uc. If the RTC prescaler is accessible register, you can do it in shorter time.Some crystal values may not be possible to use as the USB needs 48MHz clock and the PLL does not have fractional divider. Some USB stacks can run crystalless from internal RC oscillator, that makes things easier. Also from every xtal freq you can not get same system clock (again, things do not divide evenly), so you may have to support multiple system clock speeds (different uart prescalers etc).

author: technix
author_rank: Super Contributor
timestamp: December 26, 2016, 01:56:35 am
content: Quote from: dgtl on December 25, 2016, 07:34:58 pmI am only supporting the frequencies listed above (3/4/6/8/12/16MHz) or else it is using HSI. Does this sequence makes sense:0. The processor starts clocked with HSI oscillator.1. Start the HSE oscillator and clock the processor off it.2. Start the LSI oscillator and configure one of the internal timers to be clocked off that oscillator.3. Set up timer match event to clear the timer and trigger an interrupt. Start the timer4. Main loop spin waits.5. When interrupt fires: Note the DWT->CYCCNT at that moment6. When I get a few readings, stop the timer and interrupt. Calculate the LSI to HSE ratio that way.7. Configure the PLL accordingly.

author: dgtl
author_rank: Regular Contributor
timestamp: December 26, 2016, 10:22:56 am
content: Afaik you can't clock timers from LSI. You can use RTC, but waiting for one second increment is slow.On STM32-s you can clock timers from system clock as usual, but set up this LSI measurement capture and let the HW capture the timestamp of an LSI edge twice. Substract and you have the LSI period measured in HSE clocks.Alternatively, read RTC prescaler current value. Wait a known number of cycles. Read the RTC prescaler again. Substract and you have the length of your delay loop in number of LSI clocks. You can for example start a timer on HSE clock and use timer rollover (irq) for a delay.

author: technix
author_rank: Super Contributor
timestamp: December 26, 2016, 10:30:00 am
content: How about this:1. Start RTC.2. Click the processor from HSE.3. Set up SysTick for 1000 cycles.4. Wait for SysTick to fire twice.5. The prescaler difference between the two SysTick events is the ratio between HSE and LSE.

author: Jeroen3
author_rank: Super Contributor
timestamp: December 26, 2016, 02:43:03 pm
content: Timer 5 has an input capture channel on the LSI clock. It is intended to use for LSI calibration, but can be used in reverse for HSE rough range detection. It's a selftest in my code to check if the crystals are still there. Since you can use it twice, and then you can compare it to HSI.Eg: hsi-tim5-lsi, hse-tim5-lsi.LSI won't drift in 5 seconds, so it'll work on HSI accuracy.See my earlier post.Also note that dwt-cyccnt is not raw clocks. It's in the trace part, which means you have to enable debug functionalty.Sample code, always better:Code: (c)/*** Compare Sysclk to LSI.*/uint32_t compare_sysclk_lsi(void){uint32_t c = 0, pc = 0;uint32_t i;AFIO->MAPR |= AFIO_MAPR_TIM5CH4_IREMAP;const uint32_t avg = 4;__HAL_RCC_TIM5_CLK_ENABLE();__HAL_RCC_TIM5_FORCE_RESET();__NOP();__HAL_RCC_TIM5_RELEASE_RESET();TIM5->CCMR2 = TIM_CCMR2_CC4S_0 | (0x3u<<TIM_CCMR2_IC4PSC_Pos);TIM5->CCER = TIM_CCER_CC4E;TIM5->CR1 = TIM_CR1_CEN;while(!(TIM5->SR & TIM_SR_CC4IF));pc = TIM5->CCR4;for(i=0;i<avg;i++){while(!(TIM5->SR & TIM_SR_CC4IF));c += TIM5->CCR4 - pc;pc = TIM5->CCR4;}TIM5->CR1 = 0;__HAL_RCC_TIM5_CLK_DISABLE();c = c/avg;return c;}

author: @rt
author_rank: Super Contributor
timestamp: December 31, 2016, 08:25:14 am
content: I did it reliably with a pic, but it was a one off project, so it would depend on the consistency of internal oscillators among batches of other units.Start the program with a hardware counter running with an appropriate pre-scale until watchdog timer reset.The watchdog timer doesn’t clear the values in the timer registers, and also sets a flag to tell you the program has been reset by watchdog,so next time the program starts you can read the watchdog timer flag, and look at the value in the timer registers to determine the crystal frequency,and also service the watchdog timer from there on, so it doesn’t reset again.I did this to tell 4, 6, 8, 10, 12, 16, 20, 24 & 25 MHz crystals, but again,it was only one pic, so another unit may need to be calibrated with a different table to determine timer values to determine crystal frequencies.But that could happen automatically. It would be possible for each chip to run a calibration routine once for each chip and save some values to EEPROM where you tell it once, each crystal value it’s being clocked with.Another problem I foresee is the whole thing going belly up with a big change in temperature, since the watchdog is an RC clock.This was a warm up, the real project I wanted it for with more clocks came a little later.Cheers, Brek.