Add example of detaching peripheral clock and varying system clock
This commit is contained in:
		
							parent
							
								
									49d1514123
								
							
						
					
					
						commit
						6a53ff302b
					
				@ -1,4 +1,5 @@
 | 
			
		||||
if (NOT PICO_NO_HARDWARE)
 | 
			
		||||
    add_subdirectory(detached_clk_peri)
 | 
			
		||||
    add_subdirectory(hello_48MHz)
 | 
			
		||||
    add_subdirectory(hello_gpout)
 | 
			
		||||
    add_subdirectory(hello_resus)
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								clocks/detached_clk_peri/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								clocks/detached_clk_peri/CMakeLists.txt
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
add_executable(clocks_detached_clk_peri
 | 
			
		||||
        detached_clk_peri.c
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
# Pull in our pico_stdlib which pulls in commonly used features
 | 
			
		||||
target_link_libraries(clocks_detached_clk_peri pico_stdlib)
 | 
			
		||||
 | 
			
		||||
# create map/bin/hex file etc.
 | 
			
		||||
pico_add_extra_outputs(clocks_detached_clk_peri)
 | 
			
		||||
 | 
			
		||||
# add url via pico_set_program_url
 | 
			
		||||
example_auto_set_url(clocks_detached_clk_peri)
 | 
			
		||||
							
								
								
									
										86
									
								
								clocks/detached_clk_peri/detached_clk_peri.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								clocks/detached_clk_peri/detached_clk_peri.c
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,86 @@
 | 
			
		||||
/**
 | 
			
		||||
 * Copyright (c) 2021 Raspberry Pi (Trading) Ltd.
 | 
			
		||||
 *
 | 
			
		||||
 * SPDX-License-Identifier: BSD-3-Clause
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
// By default, clk_peri (which drives the serial parts of SPI and UART) is
 | 
			
		||||
// attached directly to clk_sys, so varies if the system clock is scaled up
 | 
			
		||||
// and down. clk_peri has a multiplexer (though no divider) which allows it to
 | 
			
		||||
// be attached to other sources.
 | 
			
		||||
//
 | 
			
		||||
// If set_sys_clock_khz is called (here setting the system clock to 133 MHz),
 | 
			
		||||
// this automatically attaches clk_peri to the USB PLL, which by default we run
 | 
			
		||||
// at 48 MHz. As long as you call this *before* configuring your UART etc, the
 | 
			
		||||
// UART baud rate will then not be affected by subsequent changes to clk_sys.
 | 
			
		||||
//
 | 
			
		||||
// However, dropping clk_peri to 48 MHz limits the maximum serial frequencies
 | 
			
		||||
// that can be attained by UART and particularly SPI. This example shows how
 | 
			
		||||
// clk_peri can be attached directly to the system PLL, and the clk_sys
 | 
			
		||||
// divider can then be varied to scale the system (CPUs, DMA, bus fabric etc)
 | 
			
		||||
// frequency up and down whilst keeping clk_peri at a constant 133 MHz.
 | 
			
		||||
//
 | 
			
		||||
// The complete list of clock sources available on clk_peri can be found in
 | 
			
		||||
// hardware/regs/clocks.h:
 | 
			
		||||
//
 | 
			
		||||
// Field       : CLOCKS_CLK_PERI_CTRL_AUXSRC
 | 
			
		||||
//               0x0 -> clk_sys
 | 
			
		||||
//               0x1 -> clksrc_pll_sys
 | 
			
		||||
//               0x2 -> clksrc_pll_usb
 | 
			
		||||
//               0x3 -> rosc_clksrc_ph
 | 
			
		||||
//               0x4 -> xosc_clksrc
 | 
			
		||||
//               0x5 -> clksrc_gpin0
 | 
			
		||||
//               0x6 -> clksrc_gpin1
 | 
			
		||||
 | 
			
		||||
#include <stdio.h>
 | 
			
		||||
#include "pico/stdlib.h"
 | 
			
		||||
#include "hardware/clocks.h"
 | 
			
		||||
 | 
			
		||||
#define PLL_SYS_KHZ (133 * 1000)
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
    // Set the system frequency to 133 MHz. vco_calc.py from the SDK tells us
 | 
			
		||||
    // this is exactly attainable at the PLL from a 12 MHz crystal: FBDIV =
 | 
			
		||||
    // 133 (so VCO of 1596 MHz), PD1 = 6, PD2 = 2. This function will set the
 | 
			
		||||
    // system PLL to 133 MHz and set the clk_sys divisor to 1.
 | 
			
		||||
    set_sys_clock_khz(PLL_SYS_KHZ, true);
 | 
			
		||||
 | 
			
		||||
    // The previous line automatically detached clk_peri from clk_sys, and
 | 
			
		||||
    // attached it to pll_usb, so that clk_peri won't be disturbed by future
 | 
			
		||||
    // changes to system clock or system PLL. If we need higher clk_peri
 | 
			
		||||
    // frequencies, we can attach clk_peri directly back to system PLL (no
 | 
			
		||||
    // divider available) and then use the clk_sys divider to scale clk_sys
 | 
			
		||||
    // independently of clk_peri.
 | 
			
		||||
    clock_configure(
 | 
			
		||||
        clk_peri,
 | 
			
		||||
        0,                                                // No glitchless mux
 | 
			
		||||
        CLOCKS_CLK_PERI_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS, // System PLL on AUX mux
 | 
			
		||||
        PLL_SYS_KHZ * 1000,                               // Input frequency
 | 
			
		||||
        PLL_SYS_KHZ * 1000                                // Output (must be same as no divider)
 | 
			
		||||
    );
 | 
			
		||||
 | 
			
		||||
    // The serial clock won't vary from this point onward, so we can configure
 | 
			
		||||
    // the UART etc.
 | 
			
		||||
    stdio_init_all();
 | 
			
		||||
 | 
			
		||||
    puts("Peripheral clock is attached directly to system PLL.");
 | 
			
		||||
    puts("We can vary the system clock divisor while printing from the UART:");
 | 
			
		||||
 | 
			
		||||
    for (uint div = 1; div <= 10; ++div) {
 | 
			
		||||
        printf("Setting system clock divisor to %u\n", div);
 | 
			
		||||
        clock_configure(
 | 
			
		||||
            clk_sys,
 | 
			
		||||
            CLOCKS_CLK_SYS_CTRL_SRC_VALUE_CLKSRC_CLK_SYS_AUX,
 | 
			
		||||
            CLOCKS_CLK_SYS_CTRL_AUXSRC_VALUE_CLKSRC_PLL_SYS,
 | 
			
		||||
            PLL_SYS_KHZ,
 | 
			
		||||
            PLL_SYS_KHZ / div
 | 
			
		||||
        );
 | 
			
		||||
        printf("Measuring system clock with frequency counter:");
 | 
			
		||||
        // Note that the numbering of frequency counter sources is not the
 | 
			
		||||
        // same as the numbering of clock slice register blocks. (If we passed
 | 
			
		||||
        // the clk_sys enum here we would actually end up measuring XOSC.)
 | 
			
		||||
        printf("%u kHz\n", frequency_count_khz(CLOCKS_FC0_SRC_VALUE_CLK_SYS));
 | 
			
		||||
    }
 | 
			
		||||
    return 0;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user