This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
Hi
I have another question regarding the Timer.
I set the CCR0 to 239, however, Timer seems to kick 223 clock cycle and some for 240 clock cycle.
How can I not having an consistent clock cycle for every Timer kick.
( I also make sure that there is no other service routine interrupt timer)
Thanks
#if defined(__TI_COMPILER_VERSION__) || defined(__IAR_SYSTEMS_ICC__) #pragma vector = TIMER0_B0_VECTOR __interrupt void TIMER0_B0_ISR(void) #elif defined(__GNUC__) void __attribute__ ((interrupt(USCI_B0_VECTOR))) TIMER0_B0_ISR (void) #else #error Compiler not supported! #endif { delta[count] = RTCCNT - pre_rtc; pre_rtc = RTCCNT; count++; if (count>=120) { HWREG16(TIMER_B0_BASE + OFS_TBxCTL) &= ~MC; // process data HWREG16(TIMER_B0_BASE + OFS_TBxCTL) |= MC__UP; } }
Hi ming,
So it appears you are reading the RTC counter at time intervals you have setup for TimerB0 - correct?
Can you provide your setup code for the RTC and TimerB0?
Hi Dennis,
Yes, it is TimerB0 and RTC .
void RTCInit() { HWREG16(RTC_BASE + OFS_RTCCTL) &= ~(RTCSS_3 | RTCPS_7); HWREG16(RTC_BASE + OFS_RTCMOD) = 32767; RTC_start(RTC_BASE, RTCSS_1); } void InitTimer() { HWREG16(TIMER_B0_BASE + OFS_TBxCTL) = TBSSEL__SMCLK; HWREG16(TIMER_B0_BASE + OFS_TBxCCR0) = 239; HWREG16(TIMER_B0_BASE + OFS_TBxCCTL0) |= CCIE HWREG16(TIMER_B0_BASE + OFS_TBxCTL) |= MC__UP; }
Hi ming,
Ok, so you are clocking the RTC and TimerB using SMCLK running at 24MHz - correct so far?
You don't mention how fast CPU is operating so I will assume the same 24MHz, in which case, do you have FRAM wait states = 2?
Here are couple of experiments to try to help narrow down the problem.
1. Change your code from delta[count] = RTCCNT - pre-rtc to delta[count] = RTCCNT - 239. What do you see?
2. Keep the CPU operating at 24MHz, but divide the SMCLK down to 4MHz. What do you see?
Hi Dennis,
yes, FRAM is set NWAITS_2.
1> I change to delta[count] = RTCCNT - 240
and the delta change to F0 for most of the time .
Attach the result in the following.
This is also the concern that result should be 240 regardless any codes written in between two Timer kicks as long as instructions did not exceed 240 clock cycle. Why is it act like this by just changing one line of code? (actually i did see cases similar to this, this is most simple case to describe)
2> 4 Mhz is not really an option for us, however, if really necessary i can try it later to see the consequence.
Thanks
Hi ming,
Ok, there is something not correct here. I went back and took a second look at your RTC initialization. According to your initialization code, you are clearing the RTCSS bits, which selects 'No Clock'. What clock source did you intend to use for the RTC?
Hi Dennis,
it use smclk for the RTC.
It is a library call for RTC_start() to set the clock source
I attach the code here.
Thanks
void RTC_start(uint16_t baseAddress, uint16_t clockSource) { HWREG16(baseAddress + OFS_RTCCTL) &= ~RTCSS_3; #ifdef RTCCKSEL HWREG16(SYS_BASE + OFS_SYSCFG2) &= ~RTCCKSEL; if(clockSource == RTC_CLOCKSOURCE_ACLK) { HWREG16(SYS_BASE + OFS_SYSCFG2) |= RTCCKSEL; HWREG16(baseAddress + OFS_RTCCTL) |= RTCSS_1; } else { HWREG16(baseAddress + OFS_RTCCTL) |= clockSource; } #else HWREG16(baseAddress + OFS_RTCCTL) |= clockSource; #endif HWREG16(baseAddress + OFS_RTCCTL) |= RTCSR; }
Thanks ming for clarifying this.
So you are running the RTC, TimerB and the CPU at 24MHz, correct? This means for every SMCLK, both RTC and TimerB advance by one count. So in theory when TimerB count matches CCR0 for the very first time, RTCCNT will be equal to TimerB count, right?
Then TimerB generates an interrupt and resets the count = 0. At this same time, the CPU detects the interrupt, pushes status register and stack pointer and performs the few instructions to read the RTCCNT register. But from the very moment of the interrupt until the time the CPU reads the RTCCNT register, the SMCLK continues to advance the RTC and TimerB counts. So if it takes the CPU 20 clock cycles (as an example) to execute the code leading up to reading the RTCCNT register, the RTCCNT and TimerB will be +20 counts from when the interrupt occurred. So this means you can't only subtract 239 from RTCCNT, you need to account for the CPU time, in this case RTCCNT - 239 - 20.
Can I ask the purpose of trying to read the RTCCNT with TimerB?
Hi Dennis,
There is only one difference from my understanding. Timer interval between two kicks should be 240 cycle as long as the instructions is less than 240 cycle.
The board is read/write data from the port 1 interface.
It works when the timer can kick on the the fix interval 240.
The reference board that we get from TI did not have the controller for that traffic.
Thanks
Hi ming,
Unfortunately I don't have an FR2155 in front of me to program and try your code, but maybe you can try a quick experiment?
In your ISR, instead of reading the RTCCNT value and writing to the array, modify the code to read the TimerB count register (TB0R) and write those values to the array and show me what you capture.
Hi Dennis,
I test with two different cases. One with RTC in accumulated style and the other with RTC delta style coding. please refer to the image with two results accordingly.
The first case has TB0R counter 0x21 and the second one has TB0R counter value 0x38.
The first case has RTC counter 240 and the second one has RTC counter 220.
The instruction did not exceed the 240 clock cycle but RTC counter should be the same, right?
However, it has different RTC value and this is what we like to find out how can we fix this.
Thanks
Hi ming,
Ok, the TB0R are pretty consistent and that is exactly what I would expect. I'm not sure why the RTC count doesn't make any sense. I'll have access to a FR2155 tomorrow and will run your code to see if I can reproduce.
Hi ming,
I setup my project using your original code and it seems to work fine. I get a delta of 223 every time in the ISR.
I have attached my source code for you to try. Note, I had to use FR2355 which is in the same family with same peripherals.
#include <msp430.h> #include "driverlib/MSP430FR2xx_4xx/inc/hw_memmap.h" #include "stdint.h" #define RTC_CLOCKSOURCE_SMCLK RTCSS__SMCLK #define RTC_CLOCKSOURCE_ACLK RTCSS__XT1CLK void RTC_start(uint16_t, uint16_t); void RTCInit() { HWREG16(RTC_BASE + OFS_RTCCTL) &= ~(RTCSS_3 | RTCPS_7); HWREG16(RTC_BASE + OFS_RTCMOD) = 32767; RTC_start(RTC_BASE, RTCSS_1); } void InitTimer() { HWREG16(TIMER_B0_BASE + OFS_TBxCTL) = TBSSEL__SMCLK; HWREG16(TIMER_B0_BASE + OFS_TBxCCR0) = 239; HWREG16(TIMER_B0_BASE + OFS_TBxCCTL0) |= CCIE; HWREG16(TIMER_B0_BASE + OFS_TBxCTL) |= MC__UP; } void RTC_start(uint16_t baseAddress, uint16_t clockSource) { HWREG16(baseAddress + OFS_RTCCTL) &= ~RTCSS_3; #ifdef RTCCKSEL HWREG16(SYS_BASE + OFS_SYSCFG2) &= ~RTCCKSEL; if(clockSource == RTC_CLOCKSOURCE_ACLK) { HWREG16(SYS_BASE + OFS_SYSCFG2) |= RTCCKSEL; HWREG16(baseAddress + OFS_RTCCTL) |= RTCSS_1; } else { HWREG16(baseAddress + OFS_RTCCTL) |= clockSource; } #else HWREG16(baseAddress + OFS_RTCCTL) |= clockSource; #endif HWREG16(baseAddress + OFS_RTCCTL) |= RTCSR; } int main(void) { WDTCTL = WDTPW | WDTHOLD; // Stop watchdog timer // Configure two FRAM waitstate as required by the device datasheet for MCLK // operation at 24MHz(beyond 8MHz) _before_ configuring the clock system. FRCTL0 = FRCTLPW | NWAITS_2 ; P2SEL1 |= BIT6 | BIT7; // P2.6~P2.7: crystal pins do { CSCTL7 &= ~(XT1OFFG | DCOFFG); // Clear XT1 and DCO fault flag SFRIFG1 &= ~OFIFG; } while (SFRIFG1 & OFIFG); // Test oscillator fault flag __bis_SR_register(SCG0); // disable FLL CSCTL3 |= SELREF__XT1CLK; // Set XT1 as FLL reference source CSCTL0 = 0; // clear DCO and MOD registers CSCTL1 |= DCORSEL_7; // Set DCO = 24MHz CSCTL2 = FLLD_0 + 731; // DCOCLKDIV = 24MHz __delay_cycles(3); __bic_SR_register(SCG0); // enable FLL while(CSCTL7 & (FLLUNLOCK0 | FLLUNLOCK1)); // FLL locked CSCTL4 = SELMS__DCOCLKDIV | SELA__XT1CLK; // set XT1 (~32768Hz) as ACLK source, ACLK = 32768Hz // default DCOCLKDIV as MCLK and SMCLK source P1DIR |= BIT0 | BIT1 | BIT2; // set ACLK SMCLK and LED pin as output P1SEL1 |= BIT0 | BIT1; // set ACLK and SMCLK pin as second function PM5CTL0 &= ~LOCKLPM5; // Disable the GPIO power-on default high-impedance mode // to activate previously configured port settings RTCInit(); InitTimer(); _enable_interrupts(); while(1) { LPM0; } } uint16_t delta[128]; uint16_t count, pre_rtc; #pragma vector = TIMER0_B0_VECTOR __interrupt void TIMER0_B0_ISR(void) { delta[count] = RTCCNT - pre_rtc; pre_rtc = RTCCNT; count++; if (count>=120) { HWREG16(TIMER_B0_BASE + OFS_TBxCTL) &= ~MC; /* set a break point on nop() */ _nop(); HWREG16(TIMER_B0_BASE + OFS_TBxCTL) |= MC__UP; } }
**Attention** This is a public forum