source: rtems/c/src/lib/libbsp/arm/beagle/pwm/README @ 55bde66

Last change on this file since 55bde66 was 55bde66, checked in by Punit Vara <punitvara@…>, on Jul 17, 2016 at 1:40:30 PM

beagle: pwm polishing

. added a README to pwm
. added select_pwmss() to select pwmss-generic registers, as opposed

to PWM-specific registers

. added pwmss_clock_en_status(), beagle_pwmss_is_running() and pwmss_tb_clock_check()
. other API improvements
. style improvements

  • Property mode set to 100644
File size: 6.3 KB
Line 
1Pulse Width Modulation subsystem includes EPWM, ECAP , EQEP. There are
2different instances available for each one. For PWM there are three
3different individual EPWM module 0 , 1 and 2. So wherever pwmss word is
4used that affects whole PWM sub system such as EPWM, ECAP and EQEP. This code
5has only implementation Non high resolution PWM module. APIs for high
6resolution PWM has been yet to develop.
7
8For Each EPWM instance, has two PWM channels, e.g. EPWM0 has two channel
9EPWM0A and EPWM0B. If you configure two PWM outputs(e.g. EPWM0A , EPWM0B)
10in the same device, then they *must* be configured with the same frequency.
11Changing frequency on one channel (e.g EPWMxA) will automatically change
12frequency on another channel(e.g. EPWMxB). However, it is possible to set
13different pulse-width/duty cycle to different channel at a time. So always
14set the frequency first and then pulse-width/duty cycle.
15
16For more you can refer :
17http://www.ofitselfso.com/BBBCSIO/Source/PWMPortEnum.cs.html
18 
19Pulse Width Modulation uses the system frequency of Beagle Bone Black.
20
21System frequency = SYSCLKOUT, that is, CPU clock. TBCLK = SYSCLKOUT(By Default)
22SYCLKOUT = 100 MHz
23
24Please visit following link to check why SYSCLKDIV = 100MHz:
25https://groups.google.com/forum/#!topic/beagleboard/Ed2J9Txe_E4
26(Refer Technical Reference Manual (TRM) Table 15-41 as well)
27
28To generate different frequencies with the help of PWM module , SYSCLKOUT
29need to be scaled down, which will act as TBCLK and TBCLK will be base clock
30for the pwm subsystem.
31
32TBCLK = SYSCLKOUT/(HSPCLKDIV * CLKDIV)
33
34                 |----------------|
35                 |     clock      |
36 SYSCLKOUT--->   |                |---> TBCLK
37                 |   prescale     |
38                 |----------------|         
39                   ^           ^
40                   |           |
41 TBCTL[CLKDIV]-----            ------TBCTL[HSPCLKDIV]
42
43
44CLKDIV and HSPCLKDIV bits are part of the TBCTL register (Refer TRM).
45CLKDIV - These bits determine part of the time-base clock prescale value.
46Please use the following values of CLKDIV to scale down sysclk respectively.
470h (R/W) = /1
481h (R/W) = /2
492h (R/W) = /4
503h (R/W) = /8
514h (R/W) = /16
525h (R/W) = /32
536h (R/W) = /64
547h (R/W) = /128
55
56These bits determine part of the time-base clock prescale value.
57Please use following value of HSPCLKDIV to scale down sysclk respectively
580h (R/W) = /1
591h (R/W) = /2
602h (R/W) = /4
613h (R/W) = /6
624h (R/W) = /8
635h (R/W) = /10
646h (R/W) = /12
657h (R/W) = /14
66
67For example, if you set CLKDIV = 3h and HSPCLKDIV= 2h Then
68SYSCLKOUT will be divided by (1/8)(1/4). It means SYSCLKOUT/32
69
70How to generate frequency ?
71
72freq = 1/Period
73
74TBPRD register is responsible to generate the frequency. These bits determine
75the period of the time-base counter.
76
77By default TBCLK = SYSCLKOUT = 100 MHz
78
79Here by default period is 1/100MHz = 10 nsec
80
81Following example shows value to be loaded into TBPRD
82 
83e.g. TBPRD = 1 = 1 count
84  count x Period = 1 x 1ns = 1ns
85  freq = 1/Period = 1 / 1ns = 100 MHz
86
87For duty cycle CMPA and CMPB are the responsible registers.
88
89To generate single with 50% Duty cycle & 100MHz freq.
90 
91 CMPA = count x Duty Cycle
92       = TBPRD x Duty Cycle
93       = 1 x 50/100
94       = 0.2
95
96The value in the active CMPA register is continuously compared to
97the time-base counter (TBCNT). When the values are equal, the
98counter-compare module generates a "time-base counter equal to
99counter compare A" event. This event is sent to the action-qualifier
100where it is qualified and converted it into one or more actions.
101These actions can be applied to either the EPWMxA or the
102EPWMxB output depending on the configuration of the AQCTLA and
103AQCTLB registers.
104 
105List of pins for that can be used for different PWM instance :
106
107  ------------------------------------------------
108  |  EPWM2        | EPWM1         | EPWM0        |
109  ------------------------------------------------
110  |  BBB_P8_13_2B | BBB_P8_34_1B  | BBB_P9_21_0B | 
111  |  BBB_P8_19_2A | BBB_P8_36_1A  | BBB_P9_22_0A |
112  |  BBB_P8_45_2A | BBB_P9_14_1A  | BBB_P9_29_0B |
113  |  BBB_P8_46_2B | BBB_P9_16_1B  | BBB_P9_31_0A |
114  ------------------------------------------------
115BBB_P8_13_2B represents P8 Header , pin number 13 , 2nd PWM instance and B channel.
116
117Following sample program can be used to generate 7 Hz frequency.
118
119#ifdef HAVE_CONFIG_H
120#include "config.h"
121#endif
122
123#include <rtems/test.h>
124#include <bsp.h>
125#include <bsp/gpio.h>
126#include <stdio.h>
127#include <stdlib.h>
128#include <bsp/bbb-pwm.h>
129
130const char rtems_test_name[] = "Testing PWM driver";
131rtems_printer rtems_test_printer;
132
133static void inline delay_sec(int sec)
134{
135  rtems_task_wake_after(sec*rtems_clock_get_ticks_per_second());
136
137
138rtems_task Init(rtems_task_argument argument);
139
140rtems_task Init(
141        rtems_task_argument ignored
142)
143{
144  rtems_test_begin();
145  printf("Starting PWM Testing");
146 
147  /*Initialize GPIO pins in BBB*/
148  rtems_gpio_initialize();
149 
150  /* Set P9 Header , 21 Pin number , PWM B channel and 0 PWM instance to generate frequency*/
151  beagle_epwm_pinmux_setup(BBB_P9_21_0B,BBB_PWMSS0);
152 
153/** Initialize clock for PWM sub system
154  * Turn on time base clock for PWM o instance
155  */
156  beagle_pwm_init(BBB_PWMSS0);
157
158  float PWM_HZ = 7.0f ;           /* 7 Hz */
159  float duty_A = 20.0f ;          /* 20% Duty cycle for PWM 0_A output */
160  const float duty_B = 50.0f ;    /* 50% Duty cycle for PWM 0_B output*/
161 
162  /*Note: Always check whether pwmss clocks are enabled or not before configuring PWM*/
163  bool is_running = beagle_pwmss_is_running(BBB_PWMSS2);
164 
165  if(is_running) {
166 
167  /*To analyse the two different duty cycle Output should be observed at P8_45 and P8_46 pin number */
168  beagle_pwm_configure(BBB_PWMSS0, PWM_HZ ,duty_A , duty_B);
169  printf("PWM  enable for 10s ....\n");
170 
171  /*Set Up counter and enable pwm module */
172  beagle_pwm_enable(BBB_PWMSS0);
173  delay_sec(10);
174 
175  /*freeze the counter and disable pwm module*/
176  beagle_epwm_disable(BBB_PWMSS0);
177  }
178}
179
180/* NOTICE: the clock driver is enabled */
181#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
182#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
183
184#define CONFIGURE_MAXIMUM_TASKS            1
185#define CONFIGURE_USE_DEVFS_AS_BASE_FILESYSTEM
186
187#define CONFIGURE_MAXIMUM_SEMAPHORES    1
188
189#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
190
191#define CONFIGURE_EXTRA_TASK_STACKS         (2 * RTEMS_MINIMUM_STACK_SIZE)
192
193#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
194
195#define CONFIGURE_INIT
196#include <rtems/confdefs.h>
197
Note: See TracBrowser for help on using the repository browser.