Hi Unmesh
I have tested an implementation on the LM3S8962. This has 3 PWM generators (up to 6 outputs).
The description has been updated in the HW timer document
http://www.utasker.com/docs/uTasker/uTaskerHWTimers.PDF, whereby the following is an extract of the new part:
The LM3Sxxxx has optional PWM generators. Each available one has two channel outputs which are named internally channel A and B for each generator. Externally the naming of the PWM outputs counts from 0, 1 to the highest one. For example, a device with 2 PWM generators will have outputs PWM0, PWM1, PWM2 and PWM3, whereby PWM0 and PWM are channels 0 and 1 of the first generator module and PWM2 and PWM3 are the channels 0 and 1 of the second PWM generator module.
In addition to the PWM controller, the general purpose timers can also be used to generate PWM signals. Only the PWM controller is discussed here.
To enable the PWM controller support in the µTasker project the define
SUPPORT_PWM_CONTROLLER must be set.
The following is an example of using the PWM controller together with the LM3S8962. It shows 2 PWM signals being generated, using 2 PWM from 2 generator modules. The LM3S8962 has 3 PWM modules and can thus generate up to 6 PWM output signals at the same time.
TIMER_INTERRUPT_SETUP timer_setup = {0}; // interrupt configuration parameters
timer_setup.int_type = PWM_CONFIGURATION;
timer_setup.timer_reference = 2; // PWM channel 2
timer_setup.int_type = PWM_CONFIGURATION;
timer_setup.timer_mode = PWM_DIV_1; // don't start yet
timer_setup.timer_value = PWM_FREQUENCY_VALUE(1000, 1); // generate 1000Hz on timer output
using PWM clock without divide
timer_setup.pwm_value = _PWM_PERCENT(20, PWM_FREQUENCY_VALUE(1000, 1));
// 20% PWM (high/low)
fnConfigureInterrupt((void *)&timer_setup); // enter configuration for PWM test
timer_setup.timer_reference = 5;
timer_setup.timer_mode = (TIMER_PWM_START_2 | TIMER_PWM_START_5 | PWM_DIV_1);
// generate PWM signal on these outputs
timer_setup.timer_value = PWM_FREQUENCY_VALUE(1500, 1);
timer_setup.pwm_value = _PWM_TENTH_PERCENT(706, PWM_FREQUENCY_VALUE(1500, 1));
// 70.6% PWM (high/low) on different channel
fnConfigureInterrupt((void *)&timer_setup); // enter configuration for PWM test
Note the following points:
1) Since the PWM controller is being used, and not a general purpose timer, the int_type is set to
PWM_CONFIGURATION. The
TIMER_INTERRUPT_SETUP is otherwise used as for timer control.
2) timer_reference is used to specify the PWM controller channel (0..5). In the example 2 channels (2 and 5) are configured.
3) The PWM outputs PWM2 and PWM5 are fixed on dedicated outputs, which may change with different parts. The driver code selects the appropriate peripheral function for the tested part but this needs to be verified for other parts in case they need a dedicated port configuration to be added.
4) Although the 2 channels are configured independently, their operation is not actually started until the final channel is configured. All 2 are started using
TIMER_PWM_START_2 | TIMER_PWM_START_5, which has the effect of (roughly) synchronising all 4 channels.
5) To stop channels from operating the mode flags
TIMER_PWM_STOP_2 and/or
TIMER_PWM_STOP_5 can be used. Should no further channels be running after this command the PWM controller will be powered down to save energy.
6) Since PWM0 and PWM1 (PWM2 and PWM3, etc.) are derived from the same PWM generator with a single 16 bit counter the output frequency must be the same for these two outputs. The PWM mark/space ration can however be configured independently. The two outputs are always syhchronised since they are derived from the same counter.
7) PWM outputs not belonging to the same PWM generator are free to have different frequencies. The driver doesn’t synchronise the output signals between PWM generators although the PWM controller in the LM3Sxxxx has some global synchronisation capabilities.
8 ) The PWM generator has a high degree of flexibility as to how the PWM signals are generated. The driver uses one fixed method as follows to generate the signals:
Initially the PWM output signal is at logical level ‘0’.
The PWM counter is loaded with the base frequency value and remains at ‘0’ and counts down until the count value matches the PWM value for the specific channel (A or B), at which moment the output is set to logical ‘1’.
The counter continues to count down until it reaches the value 0x0000, at which moment it is automatically reloaded with the periodic value and the output is reset to logical ‘0’ again. This results in the configured PWM mark/space value with the ‘1’ phase occurring after the ‘’0 phase (right-aligned).
9) When configuring the PWM frequency and mark/space % value a divider is also specified. This is a divider to the PWM module which must be the same for all PWM generators and channels used at the same time. It can have the values 1, 2, 4, 8, 16, 32 or 64, which must also be specified in the mode setting (
PWM_DIV_1, PWM_DIV_2, PWM_DIV_4, PWM_DIV_8, PWM_DIV_16, PWM_DIV_32 or
PWM_DIV_64) – if nothing is specified
PWM_DIV_1 is valid.
The PWM generators are therefore clocked by the system clock divided by the PWM divide value; a divide value of 1 gives the highest frequency and PWM resolutions; higher divide values allow slower signals to be generated and slightly reduced power consumption.
The new code is included in the attached zip file, which incorporates the following files:
-
ADC_Timers.h - new test code. It requires
TEST_TIMER and
TEST_PWM to be active in the file and
SUPPORT_PWM_CONTROLLER generally (usually added to
app_hw_lm3sxxxx.h).
-
LM3SXXXX.c - see
27.12.2010 Add PWM controller support {32} for the new interface code
-
LM3SXXXX.h - see the following for the new defines:
27.12.2010 Add PWM_CONFIGURATION {30}
27.12.2010 Add _LM3S1776 {31}These new files will not be fully compatible with the released project so you may need to just copy the relevant parts.
You will also see that there is a new define _LM3S1776 which is also used in the PWM port peripheral interface code to set the PWM peripheral outputs since the location of these are not the same on all chips (eg. PWM0 is on PF0 in the LM3S8962 but on PD0 in the LM3S1776). I have tried to set these up to suit the LM3S1776, which has 8 PWMx pins, but you will need to verify that all really do work since I don't have such a device for testing on.
As noted in the documentation the implementation is general so that up to 8 PWM signals can easily be configured (with the restrictions as noted). The PWM generator is however quite flexible and can be controlled in various ways, so additional tuning can be added once you have verified that the basic case works correctly.
Regards
Mark