ZYNQ: [1] In-depth understanding of the TTC timer on the PS side (Part1: principle + official case explanation)

Broken thoughts: Long time no see, I miss you so much! This issue brings the content about ZYNQ7020. We know that ZYNQ is a SOC with a hard core, and the PS side is very powerful, which can realize some algorithm verification more conveniently. This article explains the TTC timer in detail, and the Part2 released later will be based on specific projects to realize six channels of PWM output with unequal duty cycles on a single core at the PS end~

Although it didn't seem to help QAQ for my graduation in the end, after all, I spent some time reading the manual and other content, so I plan to record it for your reference.

Table of contents

1 Analysis of TTC principle

1.1 Main Features

1.2 Structural block diagram

1.3 Functional description

1.3.1 Operating modes

1.3.2 Event Timer/Pulse Width Counter (Event Timer) Operation

1.4 Register overview

1.5 Programming Model

1.5.1 Steps to enable the counter

1.5.2 Procedure for counter stop

1.5.3 Procedure for Counter Restart

1.5.4 The steps to enable the event counter (pulse width counter)

1.5.5 Procedure for Clearing Interrupts and Acknowledgments

1.6 Selection of counter clock input

2 SDK analysis

2.1 Project establishment

2.2 Case Analysis

1. Set up the interrupt system: SetupInterruptSystem()

2. Set the Ticker timer: SetupTicker() 

3. Set the PWM timer: SetupPWM()

4. Gradually modify the duty cycle: WaitForDutyCycleFull()

5. Stop the counter: XTtcPs_Stop()


1 Analysis of TTC principle

In this part, we analyze and introduce directly according to the ideas of UG585. Since the content of the original text itself is in English, it still needs some experience to understand (although it is recommended to read the original part).

TTC contains three independent timers, which are Timer/Clock 0, Timer/Clock 1, and Timer/Clock 2 in the above figure. From the lower left corner, you can see that there are two TTCs on the PS side, namely TTC0 and TTC1, so the two TTCs contain 6 independent timers in total. The TTC controller can switch between secure mode and non-secure mode by modifying the bits of the register nic301_addr_region_ctrl_registers.security_apb [ttc1_apb]. For the content of these two modes, please refer to the following:

Portal

Secure mode and Non-secure mode:
These two modes are derived from the ARM TrustZone technology. ARM introduces a special CPU mode called "safe mode" outside the normal mode of the CPU, and establishes the "safe world" and "normal world" concept. By default, the secure world accesses all state of the normal world, but not vice versa. Since ARM basically uses a structure based on memory mapping, my understanding is to realize the protection of important registers through the separation of these two modes.

1.1 Main Features

Each TTC has the following characteristics:

1. Three independent 16-bit prescalers and 16-bit up/down counters. (Up: 0, 1, 2, 3, 4... Down: 9, 8, 7, 6...)

2. Optional clock source input (internal PS bus clock: CPU_1x, internal clock: PL, external clock: MIO)

3. For each counter inside the TTC, there is an interrupt

4. An overflow interrupt within a certain interval, or an interrupt will be issued when the count matches the set value

5. Generate waveform output, which can be through MIO or PL (EMIO)

1.2 Structural block diagram

Through the above structural block diagram, the multi-channel control of the clock input and waveform output signal of the first counter Timer/Clock 0 in TTC is realized through the slcr.MIO_PIN_xx register, and the EMIO interface is used by default.

1.3 Functional description

Each prescaler module (Pre-scaler) can be independently set to use the PS internal bus clock or external clock (from MIO or PL). For external clock input, select specific signal input by using SLCR register. The prescaler module can divide the input clock between /2 and /65536. When the frequency division register is 0, the frequency of the clock will be divided by two, and then output to the following counter.

The timer can be set to count up and count down, and the range of counting can be controlled by setting the value of the interval register. At the same time, the value of the three matching registers can be compared with the value of the counter (a TTC contains 3 counters and 3 sets of matching registers), and an interrupt signal is generated.

The interrupt module combines various types of interrupts: counter interval interrupt (Interval Interrupt), counter match interrupt (Match Interrupt), counter overflow interrupt (Overflow Interrupt), event timer overflow. Each type can be enabled individually.

1.3.1 Operating modes

Each counter module in a TTC can be independently programmed and run in either of the following two modes.

Interval mode:

By modifying the DEC bit of the counter control register (Counter Control register), you can control whether the counting direction of the counter is +1 or -1. By modifying the value of the interval counter (Interval mode), the range of counting can be controlled from 0 to the value of the interval counter. When the count value passes 0, a counter interval interrupt (Interval Interrupt) will be generated. When the value of the counter is equal to the match counter (Match register) value, a match interrupt (Match Interrupt) will be generated.

Overflow mode:

The counter changes continuously between +1 or -1 between 0x0000 and 0xFFFF, and the direction of counting is controlled by modifying the DEC bit of the counter control register. When the count value passes 0, an overflow interrupt (Overflow Interrupt) will be generated. When the counter value is equal to the match counter value, a match interrupt will be generated.

1.3.2 Event Timer/Pulse Width Counter (Event Timer) Operation

From the name of the pulse width counter, it can be inferred that its function is to measure the pulse width of the external input signal. The principle is similar to the M method speed measurement of the motor differential encoder.

There is a 16-bit internal counter (Internal Counter) invisible to the user inside the event timer. This counter is controlled by the clock of CPU_1x, which meets the following two conditions:

1. When the external pulse is not in the counting phase, it is reset to 0

2. During the counting phase of the external pulse, start to increase

Modify the event timer to control the behavior of the internal counter, which is mainly controlled by three bits:

1 E_En bit Enable bit, when equal to 0, reset the internal counter to 0 and stop counting

2 E_Lo bit specifies the counting phase of the external pulse

3 E_Ov bit specifies how to handle when the internal counter overflows.

     When it is 0, the overflow causes E_En to be set to 0;

When it is 1, the overflow causes the internal counter to continue counting in a loop;

Under the control of another register, it is possible to decide whether to generate an interrupt on overflow (regardless of the value of the E_Ov bit itself).

When the count phase of the external count pulse ends, the value of the event register (Event Register) is updated with the non-zero count value of the internal counter. Therefore, this value shows the width of the external pulse. Since the internal counter is clocked by CPU_1x, the pulse width is measured by the number of clock cycles of CPU_1x.

During the count phase of the external count pulse, if the internal counter is reset to 0 due to overflow, the event register will not be updated and will keep the old value of the last non-overflow count operation.

1.4 Register overview

Function

name

overview

clock control

Clock Control Register

Control prescaler, select clock input, select edge

Counter Control Register

Enable counter, set operation mode, set count direction, enable match, enable waveform output

state

Counter Value Register

Returns the current value of the counter

counter control

interval register

set interval value

match register 1

match register 2

match register 3

Set the matching value, there are 3 groups in total, corresponding to 3 Counters inside a TTC (this statement is not accurate, in fact, each Counter has its own set of three matching registers)

to interrupt

interrupt register

Show current interrupt status

interrupt enable register

enable interrupt

event

Event Control Timer Register

Enable event timer, stop timer, set count phase

event register

Display the width of the external pulse (that is, the count value of the internal counter)

1.5 Programming Model

1.5.1 Steps to enable the counter

  1. Select the clock input source and set the prescaler value (slcr.MIO_MUX_SEL registers, TTC Clock Control register). Before this step, you need to ensure that TTC is disabled (slcr.MIO_MUX_SEL registers, TTC Clock Control register)
  2. Set interval value (Interval register), this step is optional, only in interval mode
  3. Set the matching value (Match registers), this step is optional, if the matching is enabled, it needs to be set
  4. Enable interrupt (Interrupt Enable register), this step is optional, if interrupt is required, it needs to be enabled
  5. Set the enable state of the waveform output, set the enable state of the match, set the counting direction, set the mode, enable the counter (TTC Counter Control register), this step starts the counter

1.5.2 Procedure for counter stop

  1. Read the value of the current counter controller
  2. Set DIS bit to 1, keep other bits unchanged
  3. Write the value modified above the DIS bit back to the counter controller

1.5.3 Procedure for Counter Restart

  1. Read the value of the counter controller
  2. Set RST bit to 1, keep other bits unchanged
  3. Write the value modified above the DIS bit back to the counter controller

1.5.4 The steps to enable the event counter (pulse width counter)

  1. Select the external pulse source (slcr.MIO_MUX_SEL registers), the pulse width of the selected external pulse will be measured by the period of the clock CPU_1x
  2. Set the processing when the count overflows, select the level of the external pulse, enable the event counter (select external pulse level), this step starts to measure the pulse width of the selected external pulse (high level or low level)
  3. Enable interrupt (Interrupt Enable register), this step is optional, if interrupt is required, it needs to be enabled
  4. Read the measured pulse width (Event register), and note that when the count overflow occurs, the returned pulse width count value is inaccurate. For details, see the previous description of the event counter.

1.5.5 Procedure for Clearing Interrupts and Acknowledgments

  1. Reading the interrupt register will automatically read and clear all bits in the interrupt register

1.6 Selection of counter clock input

The following shows how to set the SoC to select the clock source for Counter/timer 0 in TTC0, using a set of if else statements.

if slcr.MIO_PIN_19[6:0] is 1100000, use MIO pin 19

else if slcr.MIO_PIN_31[6:0] is 1100000, use MIO pin 31

else if slcr.MIO_PIN_43[6:0] is 1100000, use MIO pin 43

else use EMIOTTC0CLKI0

Counter/timer 1 of TTC0 can only use EMIOTTC0CLKI1

Counter/timer 2 of TTC0 can only use EMIOTTC0CLKI2

The following shows how to set the SoC to select the clock source for Counter/timer 0 in TTC1, using a set of if else statements.

if slcr.MIO_PIN_17[6:0] is 1100000, use MIO pin 17

else if slcr.MIO_PIN_29[6:0] is 1100000, use MIO pin 29

else if slcr.MIO_PIN_41[6:0] is 1100000, use MIO pin 41

else use EMIOTTC1CLKI0

Counter/timer 1 of TTC1 can only use EMIOTTC1CLKI1

Counter/timer 2 of TTC1 can only use EMIOTTC1CLKI2

IMPORTANT: When selecting a MIO pin or EMIOTTCxCLKIx as a clock source, if the clock stops running, the corresponding count value register will retain the old value regardless of the fact that the clock has stopped. Caution must be exercised in this situation. This sentence is understood to mean that the fact that the clock stopped running may be easily overlooked.

2 SDK analysis

2.1 Project establishment

Perform the following configuration in any ZYNQ project:

Check TTC0 and TTC1 here, and there will be 6 more Pins in Block Design. (Prepare for the 6 duty cycle PWM output in the next issue~)

Right click on each Pin and set Make External:

Then bind the output pins in the xdc file.

At the same time, you can see the frequency of the clock in Clock Configuration, where it shows that the clock source of TTC1 and TTC2 is from the internal clock of CPU_1x, and the frequency is 133.333333MHz

At this point, the Block Design part is set up.

After modifying the Block Design first, you need to click F6 to perform the Validate Design operation to verify the correctness of the Block Design.

Then click Generate Output Products to generate the output.

Next click Generate Bitstream on the left to output the bitstream file.

Then click File-Export-Export Hardware to export the hardware information.

Then click File-Lauch SDK to create an empty project. (The process of this step can refer to the embedded development series of ZYNQ series videos of the leader of punctual atoms)

After opening the SDK file corresponding to the Vivado project, we can find some ttc reference files provided on the left:

We only need to pay attention to the header file xttcps.h, which is the header file of the TTC module driver in PS, and gives a more detailed function definition

Also find some example files:

Here we mainly explain the code of the first case.

2.2 Case Analysis

Here, readers need to open the above case file by themselves~ Since no additional hardware settings are required, the above content can be seen directly in the SDK.

Here we briefly introduce the ttc setting process for this file.

This document internally gives a case of using TTC to generate an interrupt, which is divided into several steps.

1. Set up the interrupt system: SetupInterruptSystem()

Line547+552: Initialize the interrupt controller

Line562: Register interrupt handling

Line569: Enable interrupt

2. Set the Ticker timer: SetupTicker() 

It should be noted that SetupTicker contains the initialization of information, the setting of a single timer, and the setting of interrupts. It is equivalent to combining these parts together.

The function starts from Line257, which refers to a data structure TmrCntrSetup, defined in Line100

typedef struct {
    u32 OutputHz;    /* Output frequency */
    XInterval Interval;    /* Interval value */
    u8 Prescaler;    /* Prescaler value */
    u16 Options;    /* Option settings */
} TmrCntrSetup;

And Line261 calls the array defined by Line131: 

static TmrCntrSetup SettingsTable[2] = {
    {100, 0, 0, 0},    /* Ticker timer counter initial setup, only output freq */
    {200, 0, 0, 0}, /* PWM timer counter initial setup, only output freq */
}; 

It can be seen that this array is used to set the status of Ticker timer and PWM timer respectively, including: output frequency; interval value; prescaler coefficient; output option setting.

The setting of the output option is realized by the OR operation in Line267. The specific optional parameters can be found in the definition in xttcps.h:

Going back to xttcps_intr_example, Line267 defines the current mode as the interval mode, and at the same time sets no waveform output. (If the output waveform is set here, when the counter value is equal to the matching value, the output will be reversed to realize the waveform output).

After that, the SetupTimer function is called in Line275 to realize the specific setting of a single timer. This function is defined in Line469. Note that the transmission of information is realized through TTC_TICK_DEVICE_ID.

The main function is to initialize the device (XTtcPs_LookupConfig, XTtcPs_CfgInitialize), and pass the settings in SetupTicker, including (setting option mode XTtcPs_SetOptions, calculating interval value XTtcPs_CalcIntervalFromFreq, setting interval value XTtcPs_SetInterval, setting prescaler coefficient XTtcPs_SetPrescaler)

After the setting is completed, the set device TtcPsTick is obtained.

Back in SetupTicker, Line285 implements the setting of the interrupt controller, defines the device and the interrupt processing function.

The interrupt handler function TickHandler is defined in Line592, first obtain the interrupt type in Line599, and then clear the interrupt in Line600. Judge the type of interrupt at Line602, here is XTTCPS_IXR_INTERVAL_MASK, its definition and other types of interrupts, we can find it in xttcps_hw.h, which defines six types of interrupts:

When the corresponding type of interruption is detected, we use TickCount to accumulate the number of interval terminal occurrences.

Back in SetupTicker, the interrupt enable operation is performed on Line294 and Line300, and then the timer is set on Line305.

3. Set the PWM timer: SetupPWM()

I believe this is also the part that many people pay more attention to.

Line328 implements some setting information, mainly storing the second element of the previous array.

Line334 sets the interval mode, match mode, and enables the output of wave, which ensures that when the count value is the same as the match value, the output signal will be reversed. Therefore, the interval value can be used to set the PWM period, and the matching value can be used to set the PWM duty cycle.

Line342 also calls SetupTimer to realize the specific setting of a single timer. For details, please refer to the above part. This function is defined in Line469. Note that the transmission of information is realized through TTC_PWM_DEVICE_ID.

The main function is to initialize the device (XTtcPs_LookupConfig, XTtcPs_CfgInitialize), and pass the settings in SetupPWM, including (setting option mode XTtcPs_SetOptions, calculating interval value XTtcPs_CalcIntervalFromFreq, setting interval value XTtcPs_SetInterval, setting prescaler coefficient XTtcPs_SetPrescaler)

After the setting is completed, the set device TtcPsPWM is obtained

Line352 realizes setting of interrupt controller, device ID, interrupt processing function and matching value pointer by calling XScuGic_Connect.

The interrupt processing function PWMHandler is defined in Line637. When the interrupt signal is detected to be an interval interrupt (that is, a cycle is output), it will call XTtcPs_SetMatchValue in Line653 to set the matching value. It is mentioned in the code comment that the matching register 0 is a special Yes, if the output is enabled, the polarity of the output is modified when the match value is equal to the count value.

But the note here is easy to be misunderstood. The functions of the three matching registers of the TTC timer are inconsistent, and not all of them can be used for waveform output. In the official ZYNQ example, register0 is designated as Special, that is, when the counter When it is equal to the matching value of register0, a special interrupt event will be triggered and the output level will be inverted. Experiments have shown that for the same Counter, register1 and register2 will not affect the inversion of PWM output, but since there are three Counters in each TTC, in fact, three values ​​of register0 can be set to achieve three PWMs with different duty ratios. Output.

Back in SetupPWM, the interrupt enable operation is performed on Line361 and Line367, and then the timer is set on Line372.

4. Gradually modify the duty cycle: WaitForDutyCycleFull()

This function is defined in Line397, mainly through the TickHandler function will update PWM_UpdateFlag to TRUE in Line607 after each cycle outputs a PWM wave, and then satisfy the if condition in WaitForDutyCycleFull, thereby modifying the value of the global variable MatchValue. Through Line643 in the interrupt processing function PWMHandler, the assignment of MatchValue to MatchReg is realized, so that the value of MatchReg can be modified in Line653, and then the duty cycle can be modified.

The overall logic only needs to grasp the following three points: 1. Interval mode interrupt: update the flag at the end of the PWM cycle; 2. Modify the duty cycle: detect the flag to modify the global variable and change the duty cycle; 3. PWM output interrupt processing function (also interval mode interrupt) to set the matching value in.

5. Stop the counter: XTtcPs_Stop()

Here, XTtcPs_Stop is directly called on Line236 and Line238 to stop the counter.


This is the whole content of this issue. If you like my article, don't forget to like + bookmark + follow, and share it with your friends~

Guess you like

Origin blog.csdn.net/Alex497259/article/details/130188608