h1r9: use timer to detect external clock frequency

This commit is contained in:
Michael Ossmann
2022-08-26 05:47:22 -04:00
committed by Mike Walters
parent 6f26b74e90
commit 8aa79e9fe5
5 changed files with 153 additions and 3 deletions

114
firmware/common/clkin.c Normal file
View File

@ -0,0 +1,114 @@
/*
* Copyright 2022 Great Scott Gadgets
*
* This file is part of HackRF.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#include "gpdma.h"
#include <libopencm3/lpc43xx/timer.h>
#include <libopencm3/lpc43xx/scu.h>
#include <libopencm3/lpc43xx/gima.h>
#include <stdint.h>
#define CLOCK_CYCLES_1_MS (204000)
#define MEASUREMENT_WINDOW_MS (50)
#define MEASUREMENT_CYCLES (CLOCK_CYCLES_1_MS * MEASUREMENT_WINDOW_MS)
/* DMA linked list item */
typedef struct {
uint32_t src;
uint32_t dest;
uint32_t next_lli;
uint32_t control;
} dma_lli;
/* timer control register configuration sequence */
typedef struct {
uint32_t first_tcr;
uint32_t second_tcr;
} tcr_sequence;
dma_lli timer_dma_lli;
tcr_sequence reset;
void clkin_detect_init(void)
{
/* Timer3 triggers periodic measurement */
timer_set_prescaler(TIMER3, 0);
timer_set_mode(TIMER3, TIMER_CTCR_MODE_TIMER);
TIMER3_MCR = TIMER_MCR_MR0R;
TIMER3_EMR = TIMER_EMR_EM0 | TIMER_EMR_EM3 |
(TIMER_EMR_EMC_SET << TIMER_EMR_EMC0_SHIFT) |
(TIMER_EMR_EMC_TOGGLE << TIMER_EMR_EMC3_SHIFT);
TIMER3_MR3 = MEASUREMENT_CYCLES;
TIMER3_MR0 = MEASUREMENT_CYCLES;
/* Timer0 counts CLKIN */
timer_set_prescaler(TIMER0, 0);
TIMER0_CCR = TIMER_CCR_CAP3RE;
GIMA_CAP0_3_IN = 0x20; // T3_MAT3
/* measure CLKIN signal on P2_5, pin 91, CTIN_2 */
TIMER0_CTCR = TIMER_CTCR_MODE_COUNTER_RISING | TIMER_CTCR_CINSEL_CAPN_2;
scu_pinmux(P2_5, SCU_GPIO_PDN | SCU_CONF_FUNCTION1);
GIMA_CAP0_2_IN = 0x00; // CTIN_2
// temporarily testing with T0_CAP1, P1_12, pin 56, P28 pin 4
//TIMER0_CTCR = TIMER_CTCR_MODE_COUNTER_RISING | TIMER_CTCR_CINSEL_CAPN_1;
//scu_pinmux(P1_12, SCU_GPIO_PDN | SCU_CONF_FUNCTION4);
//GIMA_CAP0_1_IN = 0x20; // T0_CAP1
reset.first_tcr = TIMER_TCR_CEN | TIMER_TCR_CRST;
reset.second_tcr = TIMER_TCR_CEN;
timer_dma_lli.src = (uint32_t) & (reset);
timer_dma_lli.dest = (uint32_t) & (TIMER0_TCR);
timer_dma_lli.next_lli = (uint32_t) & (timer_dma_lli);
timer_dma_lli.control = GPDMA_CCONTROL_TRANSFERSIZE(2) |
GPDMA_CCONTROL_SBSIZE(0) // 1
| GPDMA_CCONTROL_DBSIZE(0) // 1
| GPDMA_CCONTROL_SWIDTH(2) // 32-bit word
| GPDMA_CCONTROL_DWIDTH(2) // 32-bit word
| GPDMA_CCONTROL_S(0) // AHB Master 0
| GPDMA_CCONTROL_D(1) // AHB Master 1
| GPDMA_CCONTROL_SI(1) // increment source
| GPDMA_CCONTROL_DI(0) // do not increment destination
| GPDMA_CCONTROL_PROT1(0) // user mode
| GPDMA_CCONTROL_PROT2(0) // not bufferable
| GPDMA_CCONTROL_PROT3(0) // not cacheable
| GPDMA_CCONTROL_I(0); // interrupt disabled
gpdma_controller_enable();
GPDMA_C0SRCADDR = timer_dma_lli.src;
GPDMA_C0DESTADDR = timer_dma_lli.dest;
GPDMA_C0LLI = timer_dma_lli.next_lli;
GPDMA_C0CONTROL = timer_dma_lli.control;
GPDMA_C0CONFIG = GPDMA_CCONFIG_DESTPERIPHERAL(0x7) // T3_MAT0
| GPDMA_CCONFIG_FLOWCNTRL(1) // memory-to-peripheral
| GPDMA_CCONFIG_H(0); // do not halt
gpdma_channel_enable(0);
/* start counting */
timer_reset(TIMER0);
timer_reset(TIMER3);
timer_enable_counter(TIMER0);
timer_enable_counter(TIMER3);
}
uint32_t clkin_frequency(void)
{
return TIMER0_CR3 * (1000 / MEASUREMENT_WINDOW_MS);
};

30
firmware/common/clkin.h Normal file
View File

@ -0,0 +1,30 @@
/*
* Copyright 2022 Great Scott Gadgets
*
* This file is part of HackRF.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; see the file COPYING. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street,
* Boston, MA 02110-1301, USA.
*/
#ifndef __CLKIN_H__
#define __CLKIN_H__
#include <stdint.h>
void clkin_detect_init(void);
uint32_t clkin_frequency(void);
#endif //__CLKIN_H__

View File

@ -727,7 +727,7 @@ void cpu_clock_init(void)
CCU1_CLK_APB3_ADC1_CFG = 0; CCU1_CLK_APB3_ADC1_CFG = 0;
CCU1_CLK_APB3_CAN0_CFG = 0; CCU1_CLK_APB3_CAN0_CFG = 0;
CCU1_CLK_APB3_DAC_CFG = 0; CCU1_CLK_APB3_DAC_CFG = 0;
CCU1_CLK_M4_DMA_CFG = 0; //CCU1_CLK_M4_DMA_CFG = 0;
CCU1_CLK_M4_EMC_CFG = 0; CCU1_CLK_M4_EMC_CFG = 0;
CCU1_CLK_M4_EMCDIV_CFG = 0; CCU1_CLK_M4_EMCDIV_CFG = 0;
CCU1_CLK_M4_ETHERNET_CFG = 0; CCU1_CLK_M4_ETHERNET_CFG = 0;
@ -737,10 +737,10 @@ void cpu_clock_init(void)
// CCU1_CLK_M4_SCT_CFG = 0; // CCU1_CLK_M4_SCT_CFG = 0;
CCU1_CLK_M4_SDIO_CFG = 0; CCU1_CLK_M4_SDIO_CFG = 0;
CCU1_CLK_M4_SPIFI_CFG = 0; CCU1_CLK_M4_SPIFI_CFG = 0;
CCU1_CLK_M4_TIMER0_CFG = 0; //CCU1_CLK_M4_TIMER0_CFG = 0;
CCU1_CLK_M4_TIMER1_CFG = 0; CCU1_CLK_M4_TIMER1_CFG = 0;
CCU1_CLK_M4_TIMER2_CFG = 0; CCU1_CLK_M4_TIMER2_CFG = 0;
CCU1_CLK_M4_TIMER3_CFG = 0; //CCU1_CLK_M4_TIMER3_CFG = 0;
CCU1_CLK_M4_UART1_CFG = 0; CCU1_CLK_M4_UART1_CFG = 0;
CCU1_CLK_M4_USART0_CFG = 0; CCU1_CLK_M4_USART0_CFG = 0;
CCU1_CLK_M4_USART2_CFG = 0; CCU1_CLK_M4_USART2_CFG = 0;

View File

@ -185,6 +185,8 @@ macro(DeclareTargets)
${PATH_HACKRF_FIRMWARE_COMMON}/hackrf_ui.c ${PATH_HACKRF_FIRMWARE_COMMON}/hackrf_ui.c
${PATH_HACKRF_FIRMWARE_COMMON}/platform_detect.c ${PATH_HACKRF_FIRMWARE_COMMON}/platform_detect.c
${PATH_HACKRF_FIRMWARE_COMMON}/firmware_info.c ${PATH_HACKRF_FIRMWARE_COMMON}/firmware_info.c
${PATH_HACKRF_FIRMWARE_COMMON}/clkin.c
${PATH_HACKRF_FIRMWARE_COMMON}/gpdma.c
) )
if(BOARD STREQUAL "RAD1O") if(BOARD STREQUAL "RAD1O")

View File

@ -27,6 +27,7 @@
#include <libopencm3/lpc43xx/ipc.h> #include <libopencm3/lpc43xx/ipc.h>
#include <libopencm3/lpc43xx/m4/nvic.h> #include <libopencm3/lpc43xx/m4/nvic.h>
#include <libopencm3/lpc43xx/rgu.h> #include <libopencm3/lpc43xx/rgu.h>
#include <libopencm3/lpc43xx/timer.h>
#include <streaming.h> #include <streaming.h>
@ -55,6 +56,7 @@
#include "portapack.h" #include "portapack.h"
#include "hackrf_ui.h" #include "hackrf_ui.h"
#include "platform_detect.h" #include "platform_detect.h"
#include "clkin.h"
extern uint32_t __m0_start__; extern uint32_t __m0_start__;
extern uint32_t __m0_end__; extern uint32_t __m0_end__;
@ -286,6 +288,8 @@ int main(void)
} }
operacake_init(operacake_allow_gpio); operacake_init(operacake_allow_gpio);
clkin_detect_init();
while (true) { while (true) {
transceiver_request_t request; transceiver_request_t request;