You are here

PSoC Sensei Blog | Cypress Semiconductor

Jul 01, 2013

Introduction to Interrupts for PSoC 4 Hardware Blocks

With PSoC 4, new blocks in the device handle interrupts a bit differently than before with PSoC 3 and 5LP. The main difference is the usage of the Write-One-To-Clear methodology.
I'll use the TCPWM as an example of how this type of interrupt is used and controlled.  The following are the APIs that are applicable to interrupts for the TCPWM:
  • void SetInterruptMode(uint32 interruptMask)
    Used to control which interrupt sources are able to generate an interrupt. There are defined values for each of the sources. For the TCPWM an interrupt can be generated based on a terminal count or based on either a compare value or a capture. This function doesn't need to be called if the interrupt sources are configured using the component customizer. This function modifies the INTR_MASK register for the block.
  • uint32 GetInterruptSourceMasked()
    This is the function that you want to call when the interrupt fires. It allows the interrupt routine to determine which interrupt source caused the interrupt. The same defined values are used to indicate which source caused the interrupt. This function returns the value of the INTR_MASKED register for the block.
  • uint32 GetInterruptSource()
    Similar to the GetInterruptSourceMasked() function except it doesn't take into account which mask bits are enabled or disabled. This function is useful when polling for the condition to occur instead of being triggered by an interrupt. This function returns the value of the INTR register for the block.
  • void ClearInterrupt(uint32 interruptMask)
    Once the condition has occured, the interrupt bit will stay set until the bit is cleared. This function is used to clear the specified bits. This is implemented by writing a one bit to the INTR register. 
  • void SetInterrupt(uint32 interruptMask)
    With this function the interrupt can be forced to occur without requiring the actual hardware condition to occur. It will cause the interrupt condition to be seen by the hardware and software in the same way as it would be if the actual hardware interrupt had occurred. This is useful to test out the operation of the interrupt code. This function writes to the INTR_SET register for the block.
To try this out I'm going to use the TCPWM configured as a PWM and configured to generate an interrupt at each terminal count. Note that in the customizer I've configured the PWM to generate an interrupt "On terminal count" so the SetInterruptMode() function doesn't need to be called.
PWM Interrupt Schematic
Interrupt TCPWM Customizer
To use the interrupt an Interrupt Service Routine (ISR) needs to be created. There are two options. Either a function can be created and tied to the interrupt using the StartEx() function from the interrupt component, or the provided interrupt routine that is provided with the interrupt component can be edited in the merge region. I recommend that you use the StartEx() implementation because it allows you to separate your code from the generated code.
I want to monitor when the ISR code is executing so I've created a software controlled pin (PWM_isr_active) that will be high during the execution of the interrupt.
Here's the first attempt at an ISR, but it is flawed:
Interrupt Code No Clear
Looking at the waveform that is generated for the PWM_isr_active signal in yellow and the PWM_out signal in blue, you can see that the interrupt is executing more rapidly than the PWM:
Waveform ISR
The problem is that the interrupt is not being cleared, so it executes as fast as it can over and over.
Here's a second attempt at an ISR and this one clears the interrupt source before returning from the interrupt:
ISR Code
The waveform now is exactly as expected.  The ISR is triggered at the terminal count and shortly after that the pin has been written to indicate that the ISR is active. Then the interrupt completes and isn't called again until the next PWM period.:
Waveform ISR triggered
If I wanted to debug the operation of my interrupt routine I could have also just triggered the interrupt without running the PWM.  In this case however I do need to set the interrupt source since I'm not calling the PWM Start() function which sets the interrupt source based on the customizer setting:
Interrupt Code SW
The output from this test looks very similar, except that the PWM isn't running:
Waveform ISR triggered
There are other variations that can also be used with this PWM example. A polled implementation could be done using GetInterruptSource(). If this function had been called instead of GetInterruptSourceMasked() then the value returned would have shown both bits set, since the compare and the terminal count happen during each PWM period and the interrupt mask is not used for this function.
Jun 18, 2013

PSoC 4 Chained Clocks

With PSoC 4 there is another added clocking feature, chained clocks. The clock dividers in PSoC 4 come as sets of 3 clock dividers. The current devices have a total of 4 sets of 3, so 12 dividers in total.  Any of these 12 clocks can be used to drive one or more of the 16 possible destinations.
The clocks are configured in sets of 3 to allow for chaining. I'll refer to the three dividers as A, B and C. Divider A is always fed by the High Frequency (HFCLK) clock source. Divider B can be fed by either HFCLK or divider A. Divider C can be fed by either HFCLK or divider B. Fortunately you don't generally need to worry about that level of detail. Creator knows about chained clocks and it will handle which clock dividers to use.
The simplest usage of chained clocks is when you need a divider that is larger than a single divider supports. The dividers are 16 bits. If you need to divide by more than 64K, then you'll need two dividers to be chained. Creator will do this automatically. For example with a 24 MHz HFCLK a single divider cannot be used to create a 100 Hz clock. That requires a divide by 240,000. If a clock is placed in this design configured for 100 Hz, then Creator will generate this clock using two chained clock dividers and show this as a divide by 240000:
What Creator actually did was setup two chained dividers.  The first divider divides by 500 and the second divider divides by an additional 480 with the result being a divide by 240,000. In this case there are many possible choices for the two factors, but not all divider values are possible. Creator will determine the two clock divider combination that results in the closest output frequency to what is requested.
The other application for chained dividers is when two clocks must be aligned. For example if a design has a 2 MHz clock (divide by 12) and a 1 MHz clock (divide by 24), then when the clocks are started the alignment between the waveforms can't be guaranteed. These are generated by two independent dividers. All the edges of these clocks will happen at the rising edge of the 24 Mhz clock, but the alignment between these two clocks will depend on the exact amount of time between when each of the dividers is started. This relationship will also change when the clocks are stopped and restarted. The following waveform is just one possible resulting alignment:
If the design requires that the edges of the 1 MHz clock always occur on the rising edge of the 2 MHz clock, then chained clocks can be used to meet this requirement. This requires first creating a design wide clock running at 2 MHz. From the Design Wide Resources (DWR) clock tab select the Add Design-Wide Clock button at the top corner of the screen:
Then name that clock and configure it for 2 MHz:
Now use this design wide clock to create the two clocks.  First, the 2 MHz clock in the design should just be configured to use this existing Design Wide clock. In this case an additional divider is not used.
Next, the 1 MHz clock configuration needs to be changed to use the Design Wide clock as the input for the divider.  It still needs to have a new clock divider to be used in order to create that divide by 2 clock:
The DWR clock page will now show this configuration as follows:
Creator handles all the details of putting these two dividers into adjacent dividers and chaining them.
The resulting waveform now shows the clocks aligned as expected:
Jun 10, 2013

Fractional Clock Dividers with PSoC 4

One of the enhancements to clock generation that was introduced with PSoC 4 is the ability to have fractional clock dividers. By default all the clock dividers are integer clock dividers. For PSoC 4 that means that you can generate a clock whose frequency is the frequency of the High Frequency Clock (HFCLK) divided by a 16-bit integer.  For small dividers that can result in large jumps between adjacent available clock frequencies.  For example if HFCLK is running at 48 MHz, then the available clocks are 48 MHz, 24 MHz, 16 MHz, 12 MHz, ... If you want a clock that is 14 MHz, then you would need to run HFCLK at a multiple of 14 MHz (14, 28, or 42 MHz). In some cases that approach works fine, but it also changes all the other dividers in the system. An alternative solution is to divide by a fractional amount. PSoC 4 supports division by a 16 bit integer (for fractional dividers this must be at least 2) and a fraction which is a multiple of 1/32nd.  In this example you can get close to 14 MHz by dividing by 3 14/32 which yields a frequency of 13.96 MHz. Fractional dividers do however introduce jitter in the clock, so it is important to understand how they work and when you might want to use them.

The first step to understanding fractional clock dividers is to understand integer dividers. In PSoC the clock dividers are implemented off of the source clock rising edge. If the integer divider is even, then a 50% duty cycle clock is generated with the clock low for half the divider value clock periods and the clock high for the same amount of time. Here is a picture of a 3 MHz HFCLK being divided by 4 to produce a 750 kHz clock.


3 MHz HFCLK Image2
With the tolerance of the IMO on my specific device the scope measures the frequency at 752 kHz.  The clock is high for two clocks and then low for two clocks.
For an odd divider it is not possible to generate a 50% duty cycle using only the rising edge of the source clock. For the case of an odd divider the high pulse width of the generated clock will be one period longer than the low pulse width. That is shown here with the clock being divided by 3.
3 MHz HFCLK Image
In this case the low pulse width is one clock period and the high pulse width is two clock periods.
Now I'll turn our attention back to the fractional clock divider and a usage example. In this example I want to run HFCLK at 3 MHz to save power, but I want to run a UART at 115,200 baud. By default the UART is 8x oversampled, so the desired clock is 115,200 * 8 = 921.6 kHz. With integer dividers the best that can be done is 1 MHz which is 8.5% too fast.  That will result in transmission errors. Instead I can provide the UART with a clock from a clock component (select external clock in the UART component) and check the box to have Creator generate a fractional clock as shown here in the clock component customizer.
Fractional Clock Screen Image
Here are the two clock divider possibilities shown in the clock design wide resoruces display with an integer divider resulting in a 1 MHz clock (8.5% error) and with a fractional divider resulting in a 923.077 kHz clock (0.16% error). Creator shows this divider as 3 8/32 or 3.25.
Fractional Clock Diagram
The way that a 3.25x clock divider is implemented is by dividing by 3x for some periods and 4x for other periods, with the average being 3.25x. In this case the repeating pattern will be (3, 3, 3, 4). That is shown in the following scope capture. Note that the first three periods are divided by 3 and then the next is divided by 4.
Fractional Scope
The way this is implemented in the device is to divide by the smaller divider and then extend the high pulse width by one clock cycle periodically. As you can see the low pulse width is the same width as the 3x integer divider (1) and the high pulse width is either the same as the 3x divider (2) or one more (3). In hardware this is implemented by a 5 bit counter which increments by the number of 1/32nds. In this case that is 8. Each time the counter overflows the high pulse is extended by a single cycle. In this case the 8 goes into 32 evenly, so the incrementing pattern is simply (0, 8, 16, 24, 32, 0, ...) with the counter overflowing every 4 times. This approach works with any fraction, but fractions that don't divide evenly will have a longer repeating sequence. For example 15/32 has the sequence (0, 15, 30, 13, 28, 11, 26, ...) and each time it rolls over the high pulse is extended by one cycle.
Fractional clock dividers work very well for a UART. In the case of a UART the average frequency is important and the jitter in the clock is not critical. In this particular example since the UART is 8x oversampled the distance between samples turns out to be an integer number of HFCLK cycles (8 * 3.25 = 26 cycles), but even if it hadn't come out evenly the fractional clock divider would be a good choice. For other applications the jitter on the clock signal may not be acceptable. Also, only some of the clock dividers support fractional division. The current PSoC 4 devices have 12 clock dividers and 3 of those 12 support fractional clock division. When you do need a specific output frequency that you can't get with the integer dividers, consider using the fractional clock dividers and evaluate the ability of the circuit to handle the resulting clock jitter.
May 29, 2013

Using Clocks with PSoC 4

For those that have used PSoC 3 or PSoC 5LP and are now using PSoC 4, you'll notice that there are some changes between what can be done with clocks on the different devices.  There are a few new restrictions and several new capabilities.  In this post I'll take a look at using clocks in the UDB array and with pins.

The first change is that clocks can only be used as clocks.  They cannot be used as data signals.  In PSoC 3 and 5LP this was possible, but discouraged.  In PSoC 3 and 5LP the clock signals were available as clocks and also as routed signals.  The reason it was discouraged to use them as routed data signals is that the timing of these signals is not guaranteed.  That means that setup and hold is not known when a routed clock is used as a data signal and clocked by another clock.  With PSoC 4 this discouraged usage is just not allowed.  PSoC 4 only has the clocks distributed on the low skew clock lines and those are only connected to clock inputs.  As an example the following circuit will generate an error with PSoC 4.

Clock Schematic

Although this isn't the most useful circuit, what if I really needed to implement this circuit?  The solution is to convert the clock signal to a data signal.  This is easily done with a toggle flip-flop and a clock signal running 2x faster.

Toggle Clock Image

This circuit is perfectly legal.  In this case a 4 MHz clock is used instead of a 2 MHz clock.  The toggle flip-flop toggles with every 4 MHz clock edge resulting in a data signal that is a perfect square wave at 2 MHz.  The resulting signal also has a known timing relationship.  Because of that, this is also the circuit that should be used for PSoC 3 and 5LP designs as well.

One common debug application for routed clocks is to send the clock to a pin along with a data signal.  This can be done just to observe the clock during debugging.  In PSoC 3 and 5LP this is done simply by hooking a clock to an output pin.

Clock Schematic

This is not allowed on PSoC 4 since clocks can't be used as data signals.  However, PSoC 4 has some new pin capabilities and they allow the clock to be sent directly to a pin.  In fact there are a bunch of new clocking capabilities for pins.  Right now I'll just take a look at the one that allows this function to be implemented with PSoC 4.

Clock Pins Diagram

This configuration looks a little odd, but it does exactly what is desired.  The 12 MHz clock in this case is sent directly to the pin.  The clock signal needs to be sent to the out_clk terminal and the output pin terminal is just tied high.  To get to this point start with a standard output pin and then change the configuration as shown here:

Pin Output Screen

This causes the output pin to output the clock instead of the data signal.  Then make this second configuration change:

Configure CY Pins Screen Image

This configures the pin to use the clock that is being provided as the out_clk as the output clock signal for the pin.

With those changes and the signal connections shown the clock signal is once again visible on the pin.

Mar 31, 2013

Finishing Up the Square Root Component

Now that all the design work has been done for the square root component, we can do the work of creating the component in the tool. First, create a new project in PSoC Creator. Then, create a new component by right clicking your project in the Components tab, selecting "Add Component Item..." and selecting "Verilog File":

Now, load up the Datapath Configuration Tool and open the Verilog file that was created in the previous step. Select Edit->New Datapath. Choose the Instance Type to be cy_psoc3_dp8, give it a name, and click OK.

This will create a single 8-bit datapath with all of the default settings. Now we can configure the CFGRAM to implement our 8 operations. I've highlighted the important entries for each operation, as well as any that changed from the default: 

Now we can configure the static portion of the datapath configuration. There isn t much to do here. We need to make sure that our comparison is configured correctly, and that both FIFOs have dynamic mode enabled.  Everything else can stay with the default values.

Now, save the file and close the Datapath Configuration tool. The last step is editing the Verilog file to add the state machine parameter values from the last blog post, the actual state machine and a few other pieces of Verilog to complete the logic of the component. 

We'll define a few more control signals: A fifo_dyn wire to determine when the FIFOs are CPU/DMA-controlled vs. datapath-controlled, an eoc wire to indicate when computation has completed, and a cs_addr wire to dynamically select the operation. Note that this is simply the lower 3 bits of the state. We'll also need wires for each of the two conditions that we plan on using in the state machine:

The state machine is relatively simple. It can be pieced together from the state diagram:

Finally, we need to hook up our control and condition wires to the datapath:

We now have a component that configures the datapath to compute the square root of an 8-bit number. In the CJCU_Isqrt component, CJ has extended this implementation to 16, 24, and 32 bits, as well as providing APIs. For information on how to extend datapath functionality to multiple bytes, see PSoC Creator 213. To see how to design component APIs for datapath components, see PSoC Creator 214


Content on this site may contain or be subject to specific guidelines or limitations on use. All postings and use of the content on this site are subject to the Terms and Conditions of the site; third parties using this content agree to abide by any limitations or guidelines and to comply with the Terms and Conditions of this site. Cypress Semiconductor and its suppliers reserve the right to make corrections, deletions, modifications, enhancements, improvements and other changes to the content and materials, its products, programs and services at any time or to move or discontinue any content, products, programs, or services without notice.