timestamp_t lp_ticker_read() { if (! lp_ticker_inited) { lp_ticker_init(); } TIMER_T * timer2_base = (TIMER_T *) NU_MODBASE(timer2_modinit.modname); do { uint64_t major_minor_clks; uint32_t minor_clks; // NOTE: As TIMER_CNT = TIMER_CMP and counter_major has increased by one, TIMER_CNT doesn't change to 0 for one tick time. // NOTE: As TIMER_CNT = TIMER_CMP or TIMER_CNT = 0, counter_major (ISR) may not sync with TIMER_CNT. So skip and fetch stable one at the cost of 1 clock delay on this read. do { core_util_critical_section_enter(); // NOTE: Order of reading minor_us/carry here is significant. minor_clks = TIMER_GetCounter(timer2_base); uint32_t carry = (timer2_base->INTSTS & TIMER_INTSTS_TIF_Msk) ? 1 : 0; // When TIMER_CNT approaches TIMER_CMP and will wrap soon, we may get carry but TIMER_CNT not wrapped. Handle carefully carry == 1 && TIMER_CNT is near TIMER_CMP. if (carry && minor_clks > (TMR2_CLK_PER_TMR2_INT / 2)) { major_minor_clks = (counter_major + 1) * TMR2_CLK_PER_TMR2_INT; } else { major_minor_clks = (counter_major + carry) * TMR2_CLK_PER_TMR2_INT + minor_clks; } core_util_critical_section_exit(); } while (minor_clks == 0 || minor_clks == TMR2_CLK_PER_TMR2_INT); // Add power-down compensation return ((uint64_t) major_minor_clks * US_PER_SEC / TMR2_CLK_PER_SEC / US_PER_TICK); } while (0); }
void TMR1_IRQHandler(void) { // Timer clock is 1 MHz ( prescaler is set to 11 + 1), counter value records the duration for 1000 event counts. printf("Event frequency is %d Hz\n", (1000000 * 1000) / TIMER_GetCounter(TIMER1)); TIMER_ClearCaptureIntFlag(TIMER1); complete = 1; }
uint32_t us_ticker_read() { if (! ticker_inited) { us_ticker_init(); } TIMER_T *timer_base = (TIMER_T *) NU_MODBASE(TIMER_MODINIT.modname); return (TIMER_GetCounter(timer_base) / NU_TMRCLK_PER_TICK); }
uint32_t lp_ticker_read() { if (! lp_ticker_inited) { lp_ticker_init(); } TIMER_T * timer2_base = (TIMER_T *) NU_MODBASE(timer2_modinit.modname); do { uint64_t major_minor_ms; uint32_t minor_ms; // NOTE: As TIMER_CNT = TIMER_CMP and counter_major has increased by one, TIMER_CNT doesn't change to 0 for one tick time. // NOTE: As TIMER_CNT = TIMER_CMP or TIMER_CNT = 0, counter_major (ISR) may not sync with TIMER_CNT. So skip and fetch stable one at the cost of 1 clock delay on this read. do { uint32_t _state = __get_PRIMASK(); __disable_irq(); // NOTE: Order of reading minor_us/carry here is significant. minor_ms = TIMER_GetCounter(timer2_base) * MS_PER_TMR2_CLK; uint32_t carry = (timer2_base->INTSTS & TIMER_INTSTS_TIF_Msk) ? 1 : 0; // When TIMER_CNT approaches TIMER_CMP and will wrap soon, we may get carry but TIMER_CNT not wrapped. Hanlde carefully carry == 1 && TIMER_CNT is near TIMER_CMP. if (carry && minor_ms > (MS_PER_TMR2_INT / 2)) { major_minor_ms = (counter_major + 1) * MS_PER_TMR2_INT; } else { major_minor_ms = (counter_major + carry) * MS_PER_TMR2_INT + minor_ms; } __set_PRIMASK(_state); } while (minor_ms == 0 || minor_ms == MS_PER_TMR2_INT); // Add power-down compensation return (major_minor_ms / MS_PER_TICK); } while (0); }
/*---------------------------------------------------------------------------------------------------------*/ int main(void) { volatile uint32_t u32InitCount; /* Unlock protected registers */ SYS_UnlockReg(); /* Init System, peripheral clock and multi-function I/O */ SYS_Init(); /* Lock protected registers */ SYS_LockReg(); /* Init UART0 for printf */ UART0_Init(); printf("\n\nCPU @ %d Hz\n", SystemCoreClock); printf("+-------------------------------------------------+\n"); printf("| Timer1 External Counter Input Sample Code |\n"); printf("+-------------------------------------------------+\n\n"); printf("# Timer Settings:\n"); printf(" Timer1: Clock source is HCLK(50 MHz); Continuous counting mode; Interrupt enable;\n"); printf(" External counter input enable; TCMP is 56789.\n"); printf("# Connect P2.0 to T1 pin and pull P2.0 High/Low as T1 counter input source.\n\n"); /* Configure P2.0 as GPIO output pin and pull pin status to Low first */ GPIO_SetMode(P2, 0, GPIO_PMD_OUTPUT); P20 = 0; /* Initial Timer1 default setting */ TIMER_Open(TIMER1, TIMER_CONTINUOUS_MODE, 1); /* Configure Timer1 setting for external counter input function */ TIMER_SELECT_TOUT_PIN(TIMER1, TIMER_TOUT_PIN_FROM_TX_PIN); TIMER_SET_PRESCALE_VALUE(TIMER1, 0); TIMER_SET_CMP_VALUE(TIMER1, 56789); TIMER_EnableEventCounter(TIMER1, TIMER_COUNTER_FALLING_EDGE); TIMER_EnableInt(TIMER1); /* Enable Timer1 NVIC */ NVIC_EnableIRQ(TMR1_IRQn); /* Clear Timer1 interrupt counts to 0 */ g_au32TMRINTCount[1] = 0; /* Start Timer1 counting */ TIMER_Start(TIMER1); /* To check if TDR of Timer1 must be 0 as default value */ if(TIMER_GetCounter(TIMER1) != 0) { printf("Default counter value is not 0. (%d)\n", TIMER_GetCounter(TIMER1)); /* Stop Timer1 counting */ TIMER_Close(TIMER1); while(1); } /* To generate one counter event to T1 pin */ GeneratePORT2Counter(0, 1); /* To check if TDR of Timer1 must be 1 */ while(TIMER_GetCounter(TIMER1) == 0); if(TIMER_GetCounter(TIMER1) != 1) { printf("Get unexpected counter value. (%d)\n", TIMER_GetCounter(TIMER1)); /* Stop Timer1 counting */ TIMER_Close(TIMER1); while(1); } /* To generate remains counts to T1 pin */ GeneratePORT2Counter(0, (56789 - 1)); while(1) { if((g_au32TMRINTCount[1] == 1) && (TIMER_GetCounter(TIMER1) == 56789)) { printf("Timer1 external counter input function ... PASS.\n"); break; } } /* Stop Timer1 counting */ TIMER_Close(TIMER1); while(1); }
/*---------------------------------------------------------------------------------------------------------*/ int main(void) { volatile uint32_t u32InitCount; /* Unlock protected registers */ SYS_UnlockReg(); /* Init System, peripheral clock and multi-function I/O */ SYS_Init(); /* Lock protected registers */ SYS_LockReg(); /* Init UART0 for printf */ UART0_Init(); printf("\n\nCPU @ %d Hz\n", SystemCoreClock); printf("+-------------------------------------------------+\n"); printf("| Timer1 External Counter Input Sample Code |\n"); printf("+-------------------------------------------------+\n\n"); printf("# Timer Settings:\n"); printf(" Timer1: Clock source is HCLK(50 MHz); Continuous counting mode; Interrupt enable;\n"); printf(" External counter input enable; TCMP is 56789.\n"); printf("# Connect P2.0 to T1 pin and pull P2.0 High/Low as T1 counter input source.\n\n"); /* Configure P2.0 as GPIO output pin and pull pin status to Low first */ P2->PMD = 0xFFFD; P20 = 0; /* Enable Timer1 NVIC */ NVIC_EnableIRQ(TMR1_IRQn); /* Clear Timer1 interrupt counts to 0 */ g_au32TMRINTCount[1] = 0; /* Enable Timer1 external counter input function */ TIMER1->TCMPR = 56789; TIMER1->TCSR = TIMER_TCSR_CEN_Msk | TIMER_TCSR_IE_Msk | TIMER_TCSR_CTB_Msk | TIMER_CONTINUOUS_MODE; /* To check if TDR of Timer1 must be 0 as default value */ if(TIMER_GetCounter(TIMER1) != 0) { printf("Default counter value is not 0. (%d)\n", TIMER_GetCounter(TIMER1)); /* Stop Timer1 counting */ TIMER1->TCSR = 0; while(1); } /* To generate one counter event to T1 pin */ GeneratePORT2Counter(0, 1); /* To check if TDR of Timer1 must be 1 */ while(TIMER_GetCounter(TIMER1) == 0); if(TIMER_GetCounter(TIMER1) != 1) { printf("Get unexpected counter value. (%d)\n", TIMER_GetCounter(TIMER1)); /* Stop Timer1 counting */ TIMER1->TCSR = 0; while(1); } /* To generate remains counts to T1 pin */ GeneratePORT2Counter(0, (56789 - 1)); while(1) { if((g_au32TMRINTCount[1] == 1) && (TIMER_GetCounter(TIMER1) == 56789)) { printf("Timer1 external counter input function ... PASS.\n"); break; } } /* Stop Timer1 counting */ TIMER1->TCSR = 0; while(1); }