zephyr/samples/drivers/clock_control_litex
Torsten Rasmussen 1cccc8a8fe cmake: increase minimal required version to 3.20.0
Move to CMake 3.20.0.

At the Toolchain WG it was decided to move to CMake 3.20.0.

The main reason for increasing CMake version is better toolchain
support.

Better toolchain support is added in the following CMake versions:
- armclang, CMake 3.15
- Intel oneAPI, CMake 3.20
- IAR, CMake 3.15 and 3.20

Signed-off-by: Torsten Rasmussen <Torsten.Rasmussen@nordicsemi.no>
2021-08-20 09:47:34 +02:00
..
src
CMakeLists.txt cmake: increase minimal required version to 3.20.0 2021-08-20 09:47:34 +02:00
prj.conf
README.rst
sample.yaml

.. _clock_control_litex_sample:

LiteX Clock Control Driver Sample
#################################

Introduction
************

This sample is providing an overview of LiteX clock control driver capabilities.
The driver uses Mixed Mode Clock Manager (MMCM) module to generate up to 7 clocks with defined phase, frequency and duty cycle.

Requirements
************
* LiteX-capable FPGA platform with MMCM modules (for example Digilent Arty A7 development board)
* SoC configuration with VexRiscv soft CPU and Xilinx 7-series MMCM interface in LiteX (S7MMCM module)
* Optional: clock output signals redirected to output pins for testing

Configuration
*************
Basic configuration of the driver, including default settings for clock outputs, is held in Device Tree clock control nodes.

.. literalinclude:: ../../../dts/riscv/riscv32-litex-vexriscv.dtsi
   :start-at: clk0: clock-controller@0 {
   :end-at: };

.. literalinclude:: ../../../dts/riscv/riscv32-litex-vexriscv.dtsi
   :start-at: clk1: clock-controller@1 {
   :end-at: };

.. literalinclude:: ../../../dts/riscv/riscv32-litex-vexriscv.dtsi
   :start-at: clock0: clock@82005000 {
   :end-at: };

This configuration defines 2 clock outputs: ``clk0`` and ``clk1`` with default frequency set to 100MHz, 0 degrees phase offset and 50% duty cycle. Special care should be taken when defining values for FPGA-specific configuration (parameters from ``litex,divclk-divide-min`` to ``litex,vco-margin``).

**Important note:**  ``reg`` properties in ``clk0`` and ``clk1`` nodes reference the clock output number (``clkout_nr``)

Driver Usage
************

The driver is interfaced with the :ref:`Clock Control API <clock_control_api>` function ``clock_control_on()`` and a LiteX driver specific structure:

.. doxygenstruct:: litex_clk_setup
   :project: Zephyr

| To change clock parameter it is needed to cast a pointer to structure ``litex_clk_setup`` onto ``clock_control_subsys_t`` and use it with ``clock_control_on()``.
| This code will try to set on ``clk0`` frequency 50MHz, 90 degrees of phase offset and 75% duty cycle.

.. code-block:: c

	struct device *dev;
	int ret;
	struct litex_clk_setup setup = {
		.clkout_nr = 0,
		.rate = 50000000,
		.duty = 75,
		.phase = 90
	};
	dev = DEVICE_DT_GET(MMCM);
	clock_control_subsys_t sub_system = (clock_control_subsys_t*)&setup;
	if ((ret = clock_control_on(dev, sub_system)) != 0) {
		LOG_ERR("Set CLKOUT%d param error!", setup.clkout_nr);
		return ret;
	}

Clock output status (frequency, duty and phase offset) can be acquired with function ``clock_control_get_status()`` and clock output frequency only can be queried with ``clock_control_get_rate()``

In both getter functions, basic usage is similar to ``clock_control_on()``. Structure ``litex_clk_setup`` is used to set ``clkout_nr`` of clock output from which data is to be acquired.

Sample usage
************

This example provides a simple way of checking various clock output settings. User can pick one of 4 possible scenarios:

* Frequency range,
* Duty cycle range,
* Phase range,
* Setting frequency, duty and phase at once, then check clock status and rate,

Scenarios are selected by defining ``LITEX_CLK_TEST`` as one of:

* ``LITEX_TEST_FREQUENCY``
* ``LITEX_TEST_DUTY``
* ``LITEX_TEST_PHASE``
* ``LITEX_TEST_SINGLE``

Code is performed on 2 clock outputs with ``clkout_nr`` defined in ``LITEX_CLK_TEST_CLK1`` and ``LITEX_CLK_TEST_CLK2``. Tests are controlled by separate defines for each scenario.

Building
********

.. code-block:: none

  west build -b litex_vexriscv zephyr/samples/drivers/clock_control

Drivers prints a lot of useful debugging information to the log. It is highly recommended to enable logging and synchronous processing of log messages and set log level to ``Info``.

Sample output
*************

.. code-block:: none

  [00:00:00.200,000] <inf> CLK_CTRL_LITEX: CLKOUT0: set rate: 100000000 HZ
  [00:00:00.240,000] <inf> CLK_CTRL_LITEX: CLKOUT1: updated rate: 100000000 to 100000000 HZ
  [00:00:00.280,000] <inf> CLK_CTRL_LITEX: CLKOUT0: set duty: 50%
  [00:00:00.320,000] <inf> CLK_CTRL_LITEX: CLKOUT0: set phase: 0 deg
  [00:00:00.360,000] <inf> CLK_CTRL_LITEX: CLKOUT1: set rate: 100000000 HZ
  [00:00:00.400,000] <inf> CLK_CTRL_LITEX: CLKOUT1: set duty: 50%
  [00:00:00.440,000] <inf> CLK_CTRL_LITEX: CLKOUT1: set phase: 0 deg
  [00:00:00.440,000] <inf> CLK_CTRL_LITEX: LiteX Clock Control driver initialized
  *** Booting Zephyr OS build zephyr-v2.2.0-2810-g1ca5dda196c3  ***
  Clock Control Example! riscv32
  device name: clock0
  clock control device is 0x40013460, name is clock0
  Clock test
  Single test
  [00:00:00.510,000] <inf> CLK_CTRL_LITEX: CLKOUT0: set rate: 15000000 HZ
  [00:00:00.550,000] <inf> CLK_CTRL_LITEX: CLKOUT0: set phase: 90 deg
  [00:00:00.590,000] <inf> CLK_CTRL_LITEX: CLKOUT0: set duty: 25%
  [00:00:00.630,000] <inf> CLK_CTRL_LITEX: CLKOUT1: set rate: 15000000 HZ
  [00:00:00.670,000] <inf> CLK_CTRL_LITEX: CLKOUT1: set duty: 75%
  Getters test
  CLKOUT0: get_status: rate:15000000 phase:90 duty:25
  CLKOUT0: get_rate:15000000
  CLKOUT1: get_status: rate:15000000 phase:0 duty:75
  CLKOUT1: get_rate:15000000
  Clock test done returning: 0

References
**********
- :ref:`litex-vexriscv`