Warning, /bsps/arm/beagle/pwm/README.md is written in an unsupported language. File is not indexed.
0001 PWM
0002 ===
0003
0004 Pulse Width Modulation subsystem includes EPWM, ECAP , EQEP. There are
0005 different instances available for each one. For PWM there are three
0006 different individual EPWM module 0 , 1 and 2. So wherever pwmss word is
0007 used that affects whole PWM sub system such as EPWM, ECAP and EQEP. This code
0008 has only implementation Non high resolution PWM module. APIs for high
0009 resolution PWM has been yet to develop.
0010
0011 For Each EPWM instance, has two PWM channels, e.g. EPWM0 has two channel
0012 EPWM0A and EPWM0B. If you configure two PWM outputs(e.g. EPWM0A , EPWM0B)
0013 in the same device, then they *must* be configured with the same frequency.
0014 Changing frequency on one channel (e.g EPWMxA) will automatically change
0015 frequency on another channel(e.g. EPWMxB). However, it is possible to set
0016 different pulse-width/duty cycle to different channel at a time. So always
0017 set the frequency first and then pulse-width/duty cycle.
0018
0019 For more you can refer :
0020 http://www.ofitselfso.com/BBBCSIO/Source/PWMPortEnum.cs.html
0021
0022 Pulse Width Modulation uses the system frequency of Beagle Bone Black.
0023
0024 System frequency = SYSCLKOUT, that is, CPU clock. TBCLK = SYSCLKOUT(By Default)
0025 SYCLKOUT = 100 MHz
0026
0027 Please visit following link to check why SYSCLKDIV = 100MHz:
0028 https://groups.google.com/forum/#!topic/beagleboard/Ed2J9Txe_E4
0029 (Refer Technical Reference Manual (TRM) Table 15-41 as well)
0030
0031 To generate different frequencies with the help of PWM module , SYSCLKOUT
0032 need to be scaled down, which will act as TBCLK and TBCLK will be base clock
0033 for the pwm subsystem.
0034
0035 ```
0036 TBCLK = SYSCLKOUT/(HSPCLKDIV * CLKDIV)
0037
0038 |----------------|
0039 | clock |
0040 SYSCLKOUT---> | |---> TBCLK
0041 | prescale |
0042 |----------------|
0043 ^ ^
0044 | |
0045 TBCTL[CLKDIV]----- ------TBCTL[HSPCLKDIV]
0046
0047 ```
0048
0049 CLKDIV and HSPCLKDIV bits are part of the TBCTL register (Refer TRM).
0050 CLKDIV - These bits determine part of the time-base clock prescale value.
0051 Please use the following values of CLKDIV to scale down sysclk respectively.
0052
0053 ```
0054 0h (R/W) = /1
0055 1h (R/W) = /2
0056 2h (R/W) = /4
0057 3h (R/W) = /8
0058 4h (R/W) = /16
0059 5h (R/W) = /32
0060 6h (R/W) = /64
0061 7h (R/W) = /128
0062 ```
0063 These bits determine part of the time-base clock prescale value.
0064 Please use following value of HSPCLKDIV to scale down sysclk respectively
0065
0066 ```
0067 0h (R/W) = /1
0068 1h (R/W) = /2
0069 2h (R/W) = /4
0070 3h (R/W) = /6
0071 4h (R/W) = /8
0072 5h (R/W) = /10
0073 6h (R/W) = /12
0074 7h (R/W) = /14
0075 ```
0076 For example, if you set CLKDIV = 3h and HSPCLKDIV= 2h Then
0077 SYSCLKOUT will be divided by (1/8)(1/4). It means SYSCLKOUT/32
0078
0079 How to generate frequency ?
0080
0081 freq = 1/Period
0082
0083 TBPRD register is responsible to generate the frequency. These bits determine
0084 the period of the time-base counter.
0085
0086 By default TBCLK = SYSCLKOUT = 100 MHz
0087
0088 Here by default period is 1/100MHz = 10 nsec
0089
0090 Following example shows value to be loaded into TBPRD
0091
0092 ```
0093 e.g. TBPRD = 1 = 1 count
0094 count x Period = 1 x 1ns = 1ns
0095 freq = 1/Period = 1 / 1ns = 100 MHz
0096 ```
0097
0098 For duty cycle CMPA and CMPB are the responsible registers.
0099
0100 To generate single with 50% Duty cycle & 100MHz freq.
0101
0102 ```
0103 CMPA = count x Duty Cycle
0104 = TBPRD x Duty Cycle
0105 = 1 x 50/100
0106 = 0.2
0107 ```
0108 The value in the active CMPA register is continuously compared to
0109 the time-base counter (TBCNT). When the values are equal, the
0110 counter-compare module generates a "time-base counter equal to
0111 counter compare A" event. This event is sent to the action-qualifier
0112 where it is qualified and converted it into one or more actions.
0113 These actions can be applied to either the EPWMxA or the
0114 EPWMxB output depending on the configuration of the AQCTLA and
0115 AQCTLB registers.
0116
0117 List of pins for that can be used for different PWM instance :
0118
0119 ------------------------------------------------
0120 | EPWM2 | EPWM1 | EPWM0 |
0121 ------------------------------------------------
0122 | BBB_P8_13_2B | BBB_P8_34_1B | BBB_P9_21_0B |
0123 | BBB_P8_19_2A | BBB_P8_36_1A | BBB_P9_22_0A |
0124 | BBB_P8_45_2A | BBB_P9_14_1A | BBB_P9_29_0B |
0125 | BBB_P8_46_2B | BBB_P9_16_1B | BBB_P9_31_0A |
0126 ------------------------------------------------
0127
0128 BBB_P8_13_2B represents P8 Header , pin number 13 , 2nd PWM instance and B channel.
0129
0130 Following sample program can be used to generate 7 Hz frequency.
0131
0132 ```c
0133 #ifdef HAVE_CONFIG_H
0134 #include "config.h"
0135 #endif
0136
0137 #include <rtems/test.h>
0138 #include <bsp.h>
0139 #include <bsp/gpio.h>
0140 #include <stdio.h>
0141 #include <stdlib.h>
0142 #include <bsp/bbb-pwm.h>
0143
0144 const char rtems_test_name[] = "Testing PWM driver";
0145 rtems_printer rtems_test_printer;
0146
0147 static void inline delay_sec(int sec)
0148 {
0149 rtems_task_wake_after(sec*rtems_clock_get_ticks_per_second());
0150 }
0151
0152 rtems_task Init(rtems_task_argument argument);
0153
0154 rtems_task Init(
0155 rtems_task_argument ignored
0156 )
0157 {
0158 rtems_test_begin();
0159 printf("Starting PWM Testing");
0160
0161 /*Initialize GPIO pins in BBB*/
0162 rtems_gpio_initialize();
0163
0164 /* Set P9 Header , 21 Pin number , PWM B channel and 0 PWM instance to generate frequency*/
0165 beagle_epwm_pinmux_setup(BBB_P9_21_0B,BBB_PWMSS0);
0166
0167 /** Initialize clock for PWM sub system
0168 * Turn on time base clock for PWM o instance
0169 */
0170 beagle_pwm_init(BBB_PWMSS0);
0171
0172 float PWM_HZ = 7.0f ; /* 7 Hz */
0173 float duty_A = 20.0f ; /* 20% Duty cycle for PWM 0_A output */
0174 const float duty_B = 50.0f ; /* 50% Duty cycle for PWM 0_B output*/
0175
0176 /*Note: Always check whether pwmss clocks are enabled or not before configuring PWM*/
0177 bool is_running = beagle_pwmss_is_running(BBB_PWMSS2);
0178
0179 if(is_running) {
0180
0181 /*To analyse the two different duty cycle Output should be observed at P8_45 and P8_46 pin number */
0182 beagle_pwm_configure(BBB_PWMSS0, PWM_HZ ,duty_A , duty_B);
0183 printf("PWM enable for 10s ....\n");
0184
0185 /*Set Up counter and enable pwm module */
0186 beagle_pwm_enable(BBB_PWMSS0);
0187 delay_sec(10);
0188
0189 /*freeze the counter and disable pwm module*/
0190 beagle_epwm_disable(BBB_PWMSS0);
0191 }
0192 }
0193
0194 /* NOTICE: the clock driver is enabled */
0195 #define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER
0196 #define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
0197
0198 #define CONFIGURE_MAXIMUM_TASKS 1
0199 #define CONFIGURE_USE_DEVFS_AS_BASE_FILESYSTEM
0200
0201 #define CONFIGURE_MAXIMUM_SEMAPHORES 1
0202
0203 #define CONFIGURE_RTEMS_INIT_TASKS_TABLE
0204
0205 #define CONFIGURE_EXTRA_TASK_STACKS (2 * RTEMS_MINIMUM_STACK_SIZE)
0206
0207 #define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION
0208
0209 #define CONFIGURE_INIT
0210 #include <rtems/confdefs.h>
0211 ```