XMC1000 with extern oscillator

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Not applicable
Hello,

I need your help to get a correct time.

I have an extern oscillator like the app "DEV_XMC1000_Oscillator_Handling_v1_1.pdf".
There is a correct 32.768kHz signal at ACMP0.OUT but there is a time difference of 1s every hour.
I discovered that the software didn't jumpt into the isr "CCU40_1_IRQHandler(void)" to adjust the
timer and I don't know why?

Thank you for any help,
Bernd
0 Likes
13 Replies
Not applicable
Hi Bernd,

May I know what do you mean by 1s difference?
Do you mean the output frequency from ACMP0.OUT is different after 1 hour?

And you said the software did not jump into the interrupt, do you mean after 1 hour or the software did not go into interrupt at all?
0 Likes
Not applicable
Hi Jackson,

Thank you for your answer!
If I use the RTC function without the extern oszillator there is a time difference about 4second per hour.
With the extern oscillator (like the application note) the time difference is about 1sec per 2 hour.
But this is not correct enough.
I discovered that there is no jump into the interrupt service routine "CCU40_1_IRQHandler(void)" to adjust
the MCU.

Regards,
Bernd
0 Likes
User7921
Level 3
Level 3
Hi Bernd,

I use the external oszillator in all of my XMC1302 projects and it is working fine.
I did never measure the accuracy for such a long time (2 hours), but my 1ms base is now at 1ms. It was at 0.7 to 1.2 without oszi.

Here are my init values, maybe this helps.

pCaptureUnitHandle->CCU4xKernRegsPtr->GIDLC |= CCU4_GIDLC_SPRB_Msk; // Prescaler Run Bit Set
pCaptureSlicePointer->INS |= 0x02;
pCaptureSlicePointer->INS |= 0x90000; // Configures the Event 0 to be active on raising edges
pCaptureSlicePointer->CMC |= 0x0090; // External Capture on Event 0
pCaptureSlicePointer->TC = 0x1048; // Timer is cleared on a capture event
pCaptureSlicePointer->INTE = 0x0100; // Event 0 interrupt
pCaptureSlicePointer->SRS = 0x0200; // Interrupt is forward to [nö... CC4ySR0]


Look at the last SRS setting. It's different to the workaround.

Michael
0 Likes
Not applicable
Hi Michael,

Thank you for your answer but the result isn't better. The diffrence of my RTC is 1 second in 3 hour.
The ISR was never been used. Do you know why?

Regards,
Bernd
0 Likes
Not applicable
Hi BerndB,

I would like to clarify something, the trimming with external clock is actually adjusting the fractional divider of the main clock (MCLK).
This MCLK is not the clock source use by the RTC.
RTC is using the standby clock generated by DCO2 at 32.768kHz.
Therefore, trimming the MCLK with external osc has nothing to do with the RTC clock accuracy.

However, recently we found that there is a deviation in the device frequency due to some production limitation.
This issue have been rectified but for device which has already released to market could see a deviation in the device frequency.
This frequency deviation affect both DCO1 and DCO2.
And the deviation is device dependent. Therefore, every single each device could have different deviation in frequency.

As why the interrupt is not working, it could be due to the incorrect CCU4 configuration.
Based on the code provided in device guide, the interrupt is triggered when there is a raising edge of on the CCU4 input (Event 0).
Therefore, if no interrupt is triggered, it could be no input signal to CCU4, it could be interrupt was not setup properly, CCU4 not enabled.. etc.
Did you follow exactly the same code provided in the Device Guide?
0 Likes
Not applicable
Hi Jackson,

You are very friendly!

Here my code:
#include


void CCU40_1_IRQHandler (void) // N E V E R R E A C H E D
{
uint32_t Period;
uint32_t NewFDIV;
Period = CCU40_CC41->CV[1];
Period &= 0x000FFFF;
if(Period > 980)
{
NewFDIV = SCU_CLK->CLKCR;
NewFDIV++;
SCU_GENERAL->PASSWD = 0x000000C0UL;
SCU_CLK->CLKCR = NewFDIV;
while((SCU_CLK->CLKCR)&0x40000000UL); // wait for VDDC to stabilize
SCU_GENERAL->PASSWD = 0x000000C3UL;
}
else if(Period < 975)
{
NewFDIV = SCU_CLK->CLKCR;
NewFDIV--;
SCU_GENERAL->PASSWD = 0x000000C0UL;
SCU_CLK->CLKCR = NewFDIV;
while((SCU_CLK->CLKCR)&0x40000000UL); // wait for VDDC to stabilize
SCU_GENERAL->PASSWD = 0x000000C3UL;
}
}


void CMPCU_Init(void){
COMPARATOR->ANACMP0 =
((0x0 << COMPARATOR_ANACMP0_CMP_OUT_Pos) & COMPARATOR_ANACMP0_CMP_OUT_Msk) |
((0x0 << COMPARATOR_ANACMP0_CMP_LPWR_Pos) & COMPARATOR_ANACMP0_CMP_LPWR_Msk) |
((0x0 << COMPARATOR_ANACMP0_ACMP0_SEL_Pos) & COMPARATOR_ANACMP0_ACMP0_SEL_Msk) |
((0x0 << COMPARATOR_ANACMP0_CMP_HYST_ADJ_Pos)
& COMPARATOR_ANACMP0_CMP_HYST_ADJ_Msk)|
((0x0 << COMPARATOR_ANACMP0_CMP_INV_OUT_Pos)
& COMPARATOR_ANACMP0_CMP_INV_OUT_Msk) |
((0x1 << COMPARATOR_ANACMP0_CMP_FLT_OFF_Pos)
& COMPARATOR_ANACMP0_CMP_FLT_OFF_Msk) |
((0x1 << COMPARATOR_ANACMP0_CMP_EN_Pos) & COMPARATOR_ANACMP0_CMP_EN_Msk) ;
}

void PORTS_Init(void)
{
PORT0->IOCR8 =
((0x0 << PORT0_IOCR8_PC11_Pos) & PORT0_IOCR8_PC11_Msk) |
((0x14 << PORT0_IOCR8_PC10_Pos) & PORT0_IOCR8_PC10_Msk) |
((0x0 << PORT0_IOCR8_PC9_Pos) & PORT0_IOCR8_PC9_Msk) |
((0x0 << PORT0_IOCR8_PC8_Pos) & PORT0_IOCR8_PC8_Msk) ;
}

void SCU_Clock_Init (void)
{
SCU_GENERAL->PASSWD = 0x000000C0UL;
SCU_CLK->CLKCR = 0x3FF10200; // Config SCU Clock
while((SCU_CLK->CLKCR)&0x40000000UL); // wait for VDDC to stabilize
SCU_GENERAL->PASSWD = 0x000000C3UL;
SCU_GENERAL->PASSWD = 0x000000C0UL;
SCU_CLK->CGATCLR0 |= 0x04; // Disable CCU4 Gating
while((SCU_CLK->CLKCR)&0x40000000UL); // wait for VDDC to stabilize
SCU_GENERAL->PASSWD = 0x000000C3UL;
}


void CCU40_CC41_init(void)
{
// Prescaler Run Bit Set
CCU40->GIDLC |= CCU4_GIDLC_SPRB_Msk;
CCU40_CC41->INS |= 0x03;
// Configures the Event 0 to be active on raising edges
CCU40_CC41->INS |= 0x90000;
// External Capture on Event 0
CCU40_CC41->CMC |= 0x0090;
// Timer is cleared on a capture event
CCU40_CC41->TC = 0x1048;
// Event 0 interrupt
CCU40_CC41->INTE = 0x0100;
// Interrupt is forward to CC4ySR0
CCU40_CC41->SRS = 0x0100;
// Configure NVIC for interrupt
NVIC_SetPriority(CCU40_1_IRQn, 20);
NVIC_EnableIRQ(CCU40_1_IRQn);
}



void ERU0_Init(void)
{
ERU0->EXISEL &= 0xFFFC; // Event S0A from input 0A0
ERU0->EXICON[0] |= 0x0007; // Rising edge trigger, Output to OGU0
ERU0->EXOCON[0] |= 0x1024; // Enable event detection
}



int main(void){

CMPCU_Init();
PORTS_Init();
SCU_Clock_Init();
CCU40_CC41_init();
ERU0_Init();

while(1){

}
//return;
}
0 Likes
User7921
Level 3
Level 3
Hi Bernd,

don't forget to set the MCLK to a slower frequency than 32MHz.
Otherwise the workaround could only adjust in one direction.
The problem is, that the next slower MCLK frequency, that can be chosen by the factors, is 16MHz ...
But this won't solve your ISR problem.

Here's my adjustment code:
void Oszillator_SupervisorIRQHandler (void)
{
uint32_t period;
uint32_t newFDIV = (uint32_t)0;

period = CAP001_Handle0.CC4ySliceRegs0Ptr->CV[1];
period &= (uint32_t)0x000FFFF;

if(++oszillatorVars.tryCounter < (uint16_t)300)
{
if(period > (uint32_t)980)
{
newFDIV = SCU_CLK->CLKCR;
newFDIV++;
}
else if(period < (uint32_t)975)
{
newFDIV = SCU_CLK->CLKCR;
newFDIV--;
}
else
{
if(++oszillatorVars.goodCounter >= (uint16_t)5)
{
/*-----------------------------------------------------*/
/* No need to do any further trimming (at this moment) */
/*-----------------------------------------------------*/
oszillatorVars.goodCounter = (uint16_t)0;
oszillatorVars.tryCounter = (uint16_t)0;
oszillatorVars.period = (uint16_t)period;
oszillatorVars.clkCR_Value = (uint16_t)SCU_CLK->CLKCR;
Oszillator_StopTrimming();
}
}
}
else
{
oszillatorVars.goodCounter = (uint16_t)0;
oszillatorVars.tryCounter = (uint16_t)0;
oszillatorVars.period = (uint16_t)period;
oszillatorVars.clkCR_Value = (uint16_t)SCU_CLK->CLKCR;
Oszillator_StopTrimming();
}

if(newFDIV)
{
SCU_GENERAL->PASSWD = (uint32_t)0x000000C0;
SCU_CLK->CLKCR = newFDIV;

while((SCU_CLK->CLKCR) & (uint32_t)0x40000000) // wait for VDDC to stabilize
{
CPU_CLEAR_WATCHDOGS(); /* Feed the dogs */
}

SCU_GENERAL->PASSWD = (uint32_t)0x000000C3;

oszillatorVars.goodCounter = (uint16_t)0;
}

oszillatorVars.runCounter++;
}


Did you connect the comparator correctly?

877.attach

Michael
0 Likes
Not applicable
Thank you Michael,

I have the same problem with MCLK = 16MHz.

Bernd
0 Likes
Not applicable
Hi BerndB,

Looks like the capture was not run.
I think you have to add these code in your main.

CCU40->GIDLC |= CCU4_GIDLC_CS1I_Msk;
CCU40_CC41->TCSET = 0x01; // Set Run bit


But add some delay before you start capturing in order for the external signal to stabilized.
0 Likes
Not applicable
Thank you Jackson,

Here is my function but the timer didn't run!

void CCU40_CC41_init(void){
//
CCU40->GIDLC |= CCU4_GIDLC_CS1I_Msk;
CCU40_CC41->TCSET = 0x01; // Set Run bit
//

CCU40->GIDLC |= CCU4_GIDLC_SPRB_Msk; // Prescaler Run Bit Set
CCU40_CC41->INS |= 0x03;
CCU40_CC41->INS |= 0x90000; // Configures the Event 0 to be active on raising edges
CCU40_CC41->CMC |= 0x0090; // External Capture on Event 0
CCU40_CC41->TC = 0x1048; // Timer is cleared on a capture event
CCU40_CC41->INTE = 0x0100; // Event 0 interrupt
CCU40_CC41->SRS = 0x0100; // Interrupt is forward to CC4ySR0


NVIC_SetPriority(CCU40_1_IRQn, 20); // Configure NVIC for interrupt
NVIC_EnableIRQ(CCU40_1_IRQn);
}
0 Likes
Not applicable
Thank you Jackson,

I changed my code but the Timer didn't run!

void CCU40_CC41_init(void){
//
CCU40->GIDLC |= CCU4_GIDLC_CS1I_Msk;
CCU40_CC41->TCSET = 0x01; // Set Run bit
//

CCU40->GIDLC |= CCU4_GIDLC_SPRB_Msk; // Prescaler Run Bit Set
CCU40_CC41->INS |= 0x03;
CCU40_CC41->INS |= 0x90000; // Configures the Event 0 to be active on raising edges
CCU40_CC41->CMC |= 0x0090; // External Capture on Event 0
CCU40_CC41->TC = 0x1048; // Timer is cleared on a capture event
CCU40_CC41->INTE = 0x0100; // Event 0 interrupt
CCU40_CC41->SRS = 0x0100; // Interrupt is forward to CC4ySR0


NVIC_SetPriority(CCU40_1_IRQn, 20); // Configure NVIC for interrupt
NVIC_EnableIRQ(CCU40_1_IRQn);
}
0 Likes
Not applicable
Thanks to all,

I forgot this one:

//Disable the clock gating for CCU4 module
SCU_GENERAL->PASSWD = 0xC0U;
SET_BIT(SCU_CLK->CGATCLR0, SCU_CLK_CGATCLR0_CCU40_Pos);
SCU_GENERAL->PASSWD = 0xC3UL;

Regards,
Bernd
0 Likes
Not applicable
Trony wrote:
Hi Bernd,

don't forget to set the MCLK to a slower frequency than 32MHz.
Otherwise the workaround could only adjust in one direction.
The problem is, that the next slower MCLK frequency, that can be chosen by the factors, is 16MHz ...
But this won't solve your ISR problem.

Michael


Hi Michael,

I actually thought of this but I have yet tested so I can't confirm anything yet.
Since we could adjust the DCO1 frequency by ANAOFFSET register, we could purposely increase the DCO1 frequency.
What I mean is set the MCLK to 32MHz and then adjust the DCO1 to even higher by adjusting the ANAOFFSET register.
Then using the fractional divider to trim it down back to 32MHz again.
So in this case, we could adjust it to higher or lower frequency.
0 Likes