#include #include #include #include #include #include #include #include /* The devicetree node identifier for the "led0" alias. */ #define TST_CLK_PIN 18 //this is led 0 pin on nrf52-dk #define FREQ_MEASURE_PIN 18 static const struct gpio_dt_spec led = GPIO_DT_SPEC_GET(DT_ALIAS(led0), gpios); static const struct gpio_dt_spec led1 = GPIO_DT_SPEC_GET(DT_ALIAS(led1), gpios); int count = 0; void configure_clock_pin(uint32_t pin_number){ nrf_gpio_cfg( pin_number, NRF_GPIO_PIN_DIR_OUTPUT, NRF_GPIO_PIN_INPUT_CONNECT, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_S0S1, NRF_GPIO_PIN_NOSENSE); *(volatile uint32_t *)(NRF_GPIOTE_BASE + 0x600 + (4 * pin_number)) = 1; } void gpio_clock_8m(uint32_t pin_number) { NRF_TIMER0->PRESCALER = 0; // 16MHz NRF_TIMER0->SHORTS = TIMER_SHORTS_COMPARE0_CLEAR_Msk; NRF_TIMER0->CC[0] = 0x3; //~1KHz //1 for 16/2=8MHz for, 2 for 8/2=4MHz, 4 for 4/2=2MHz etc.. NRF_TIMER0->BITMODE = (TIMER_BITMODE_BITMODE_16Bit << TIMER_BITMODE_BITMODE_Pos); //using config [1] since [0] NRF_GPIOTE->CONFIG[1] = GPIOTE_CONFIG_MODE_Task | (pin_number << GPIOTE_CONFIG_PSEL_Pos) | (GPIOTE_CONFIG_POLARITY_Toggle << GPIOTE_CONFIG_POLARITY_Pos); /*Connect TIMER event to GPIOTE out task*/ NRF_PPI->CHEN |= 1 << 3; *(&(NRF_PPI->CH3_EEP)) = (uint32_t) &NRF_TIMER0->EVENTS_COMPARE[0]; *(&(NRF_PPI->CH3_TEP)) = (uint32_t) &NRF_GPIOTE->TASKS_OUT[1]; NRF_PPI->CHENSET |= 1 << 3; /*Starts clock signal*/ NRF_TIMER0->TASKS_START = 1; } static void timer_init() //gate timer { NRF_TIMER1->TASKS_STOP = 1; //trigger stop NRF_TIMER1->MODE = TIMER_MODE_MODE_Timer; //mode timer NRF_TIMER1->PRESCALER = 4; // Fhck / 2^8 -1MHz //total gate time of timer 10000 - 100mS NRF_TIMER1->CC[0] = 50000; //end gate count NRF_TIMER1->CC[1] = 1; //start gate count. don't start at 0 to no start on clear. NRF_TIMER1->BITMODE = (TIMER_BITMODE_BITMODE_32Bit << TIMER_BITMODE_BITMODE_Pos); NRF_TIMER1->TASKS_CLEAR = 1; //trigger zero timer NRF_TIMER1->INTENSET = (TIMER_INTENSET_COMPARE0_Enabled << TIMER_INTENSET_COMPARE0_Pos); //interrupt on end gate count NRF_TIMER1->EVENTS_COMPARE[0] = 0; //rest event flag for gate end NRF_TIMER1->EVENTS_COMPARE[1] = 0; //rest event flag for gate start } static void counter_init() //actual counter { NRF_TIMER2->TASKS_STOP = 1; //trigger stop NRF_TIMER2->MODE = TIMER_MODE_MODE_Counter; //counter NRF_TIMER2->BITMODE = (TIMER_BITMODE_BITMODE_24Bit << TIMER_BITMODE_BITMODE_Pos); NRF_TIMER2->TASKS_CLEAR = 1; //trigger zero counter NRF_TIMER2->EVENTS_COMPARE[0] = 0; //reset event for compare } //counter input pin setting static void gpiote_init(uint32_t pin) { NRF_GPIOTE->CONFIG[0] = 0x01 << 0; // MODE: Event NRF_GPIOTE->CONFIG[0] |= pin << 8; // Pin number NRF_GPIOTE->CONFIG[0] |= GPIOTE_CONFIG_POLARITY_LoToHi << 16; // Event rising edge } //hardware trigger: stop of counter on event of end timer1 gate static void ppi_timer_stop_counter_init() { NRF_PPI->CHEN |= 1 << 2; //channel *(&(NRF_PPI->CH2_EEP)) = (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[0]; //attach end gate event *(&(NRF_PPI->CH2_TEP)) = (uint32_t)&NRF_TIMER2->TASKS_STOP; //to counter stop trigger NRF_PPI->CHENSET |= 1 << 2; //set channel } //hardware trigger: start of counter on event of begin timer1 (gate) event.gate static void ppi_timer_start_counter_init() { NRF_PPI->CHEN |= 1 << 4;// channel *(&(NRF_PPI->CH4_EEP)) = (uint32_t)&NRF_TIMER1->EVENTS_COMPARE[1]; //attach gate start event *(&(NRF_PPI->CH4_TEP)) = (uint32_t)&NRF_TIMER2->TASKS_START; //to counter start trigger NRF_PPI->CHENSET |= 1 << 4; } static void ppi_gpiote_counter_init() //hardware attachment for the gpiote that was selected above { NRF_PPI->CHEN |= 1 << 1; *(&(NRF_PPI->CH1_EEP)) = (uint32_t)&NRF_GPIOTE->EVENTS_IN[0]; //attach pin change *(&(NRF_PPI->CH1_TEP)) = (uint32_t)&NRF_TIMER2->TASKS_COUNT;//to one count NRF_PPI->CHENSET |= 1 << 1; } //gate end interrupt handler. Count is done at hardware and percice interrupt execution isnt critical void TIMER1_IRQHandler(void) { if (NRF_TIMER1->EVENTS_COMPARE[0] != 0) //end gate event { gpio_pin_toggle_dt(&led); NRF_TIMER1->EVENTS_COMPARE[0] = 0; //reset end gate flag NRF_TIMER1->EVENTS_COMPARE[1] = 0; //reset start gate flag NRF_TIMER2->TASKS_CAPTURE[0] = 1; //trigger get counter value count = NRF_TIMER2->CC[0]; NRF_TIMER1->TASKS_CLEAR = 1; //reset timer NRF_TIMER2->TASKS_CLEAR = 1; //reset counter //NRF_TIMER1->TASKS_STOP = 1; //stop NRF_TIMER1->TASKS_START = 1; //start next count gate } } int main(void) { printf("Helloworld! \n"); nrf_gpio_cfg_input(14, NRF_GPIO_PIN_PULLUP); nrf_gpio_cfg_input(13, NRF_GPIO_PIN_PULLUP); int ret; if (!gpio_is_ready_dt(&led)) { return 0; } ret = gpio_pin_configure_dt(&led, GPIO_OUTPUT_ACTIVE); ret = gpio_pin_toggle_dt(&led); k_msleep(100); ret = gpio_pin_toggle_dt(&led); k_msleep(100); ret = gpio_pin_toggle_dt(&led); NVIC_ClearPendingIRQ(TIMER1_IRQn); NVIC_EnableIRQ(TIMER1_IRQn); //enable timer1 interrupt IRQ_CONNECT(TIMER1_IRQn, 5, TIMER1_IRQHandler, 0, 0); //link interrupt flag to handler configure_clock_pin(FREQ_MEASURE_PIN); counter_init(); timer_init(); gpiote_init(FREQ_MEASURE_PIN); // buttom in SW2 ppi_gpiote_counter_init(); ppi_timer_stop_counter_init(); ppi_timer_start_counter_init(); //test clock hardware gpio_clock_8m(FREQ_MEASURE_PIN); //start freq count task NRF_TIMER1->TASKS_START = 1; gpio_pin_set_dt(&led, 1); int old_count = 0; while (1) { k_msleep(100); if(old_count != count){ printf("cc: %dHz\n", count); //report to serial console old_count = count; } } }