Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
. 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
- Loading branch information
Showing
4 changed files
with
568 additions
and
309 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,197 @@ | ||
Pulse Width Modulation subsystem includes EPWM, ECAP , EQEP. There are | ||
different instances available for each one. For PWM there are three | ||
different individual EPWM module 0 , 1 and 2. So wherever pwmss word is | ||
used that affects whole PWM sub system such as EPWM, ECAP and EQEP. This code | ||
has only implementation Non high resolution PWM module. APIs for high | ||
resolution PWM has been yet to develop. | ||
|
||
For Each EPWM instance, has two PWM channels, e.g. EPWM0 has two channel | ||
EPWM0A and EPWM0B. If you configure two PWM outputs(e.g. EPWM0A , EPWM0B) | ||
in the same device, then they *must* be configured with the same frequency. | ||
Changing frequency on one channel (e.g EPWMxA) will automatically change | ||
frequency on another channel(e.g. EPWMxB). However, it is possible to set | ||
different pulse-width/duty cycle to different channel at a time. So always | ||
set the frequency first and then pulse-width/duty cycle. | ||
|
||
For more you can refer : | ||
http://www.ofitselfso.com/BBBCSIO/Source/PWMPortEnum.cs.html | ||
|
||
Pulse Width Modulation uses the system frequency of Beagle Bone Black. | ||
|
||
System frequency = SYSCLKOUT, that is, CPU clock. TBCLK = SYSCLKOUT(By Default) | ||
SYCLKOUT = 100 MHz | ||
|
||
Please visit following link to check why SYSCLKDIV = 100MHz: | ||
https://groups.google.com/forum/#!topic/beagleboard/Ed2J9Txe_E4 | ||
(Refer Technical Reference Manual (TRM) Table 15-41 as well) | ||
|
||
To generate different frequencies with the help of PWM module , SYSCLKOUT | ||
need to be scaled down, which will act as TBCLK and TBCLK will be base clock | ||
for the pwm subsystem. | ||
|
||
TBCLK = SYSCLKOUT/(HSPCLKDIV * CLKDIV) | ||
|
||
|----------------| | ||
| clock | | ||
SYSCLKOUT---> | |---> TBCLK | ||
| prescale | | ||
|----------------| | ||
^ ^ | ||
| | | ||
TBCTL[CLKDIV]----- ------TBCTL[HSPCLKDIV] | ||
|
||
|
||
CLKDIV and HSPCLKDIV bits are part of the TBCTL register (Refer TRM). | ||
CLKDIV - These bits determine part of the time-base clock prescale value. | ||
Please use the following values of CLKDIV to scale down sysclk respectively. | ||
0h (R/W) = /1 | ||
1h (R/W) = /2 | ||
2h (R/W) = /4 | ||
3h (R/W) = /8 | ||
4h (R/W) = /16 | ||
5h (R/W) = /32 | ||
6h (R/W) = /64 | ||
7h (R/W) = /128 | ||
|
||
These bits determine part of the time-base clock prescale value. | ||
Please use following value of HSPCLKDIV to scale down sysclk respectively | ||
0h (R/W) = /1 | ||
1h (R/W) = /2 | ||
2h (R/W) = /4 | ||
3h (R/W) = /6 | ||
4h (R/W) = /8 | ||
5h (R/W) = /10 | ||
6h (R/W) = /12 | ||
7h (R/W) = /14 | ||
|
||
For example, if you set CLKDIV = 3h and HSPCLKDIV= 2h Then | ||
SYSCLKOUT will be divided by (1/8)(1/4). It means SYSCLKOUT/32 | ||
|
||
How to generate frequency ? | ||
|
||
freq = 1/Period | ||
|
||
TBPRD register is responsible to generate the frequency. These bits determine | ||
the period of the time-base counter. | ||
|
||
By default TBCLK = SYSCLKOUT = 100 MHz | ||
|
||
Here by default period is 1/100MHz = 10 nsec | ||
|
||
Following example shows value to be loaded into TBPRD | ||
|
||
e.g. TBPRD = 1 = 1 count | ||
count x Period = 1 x 1ns = 1ns | ||
freq = 1/Period = 1 / 1ns = 100 MHz | ||
|
||
For duty cycle CMPA and CMPB are the responsible registers. | ||
|
||
To generate single with 50% Duty cycle & 100MHz freq. | ||
|
||
CMPA = count x Duty Cycle | ||
= TBPRD x Duty Cycle | ||
= 1 x 50/100 | ||
= 0.2 | ||
|
||
The value in the active CMPA register is continuously compared to | ||
the time-base counter (TBCNT). When the values are equal, the | ||
counter-compare module generates a "time-base counter equal to | ||
counter compare A" event. This event is sent to the action-qualifier | ||
where it is qualified and converted it into one or more actions. | ||
These actions can be applied to either the EPWMxA or the | ||
EPWMxB output depending on the configuration of the AQCTLA and | ||
AQCTLB registers. | ||
|
||
List of pins for that can be used for different PWM instance : | ||
|
||
------------------------------------------------ | ||
| EPWM2 | EPWM1 | EPWM0 | | ||
------------------------------------------------ | ||
| BBB_P8_13_2B | BBB_P8_34_1B | BBB_P9_21_0B | | ||
| BBB_P8_19_2A | BBB_P8_36_1A | BBB_P9_22_0A | | ||
| BBB_P8_45_2A | BBB_P9_14_1A | BBB_P9_29_0B | | ||
| BBB_P8_46_2B | BBB_P9_16_1B | BBB_P9_31_0A | | ||
------------------------------------------------ | ||
BBB_P8_13_2B represents P8 Header , pin number 13 , 2nd PWM instance and B channel. | ||
|
||
Following sample program can be used to generate 7 Hz frequency. | ||
|
||
#ifdef HAVE_CONFIG_H | ||
#include "config.h" | ||
#endif | ||
|
||
#include <rtems/test.h> | ||
#include <bsp.h> | ||
#include <bsp/gpio.h> | ||
#include <stdio.h> | ||
#include <stdlib.h> | ||
#include <bsp/bbb-pwm.h> | ||
|
||
const char rtems_test_name[] = "Testing PWM driver"; | ||
rtems_printer rtems_test_printer; | ||
|
||
static void inline delay_sec(int sec) | ||
{ | ||
rtems_task_wake_after(sec*rtems_clock_get_ticks_per_second()); | ||
} | ||
|
||
rtems_task Init(rtems_task_argument argument); | ||
|
||
rtems_task Init( | ||
rtems_task_argument ignored | ||
) | ||
{ | ||
rtems_test_begin(); | ||
printf("Starting PWM Testing"); | ||
|
||
/*Initialize GPIO pins in BBB*/ | ||
rtems_gpio_initialize(); | ||
|
||
/* Set P9 Header , 21 Pin number , PWM B channel and 0 PWM instance to generate frequency*/ | ||
beagle_epwm_pinmux_setup(BBB_P9_21_0B,BBB_PWMSS0); | ||
|
||
/** Initialize clock for PWM sub system | ||
* Turn on time base clock for PWM o instance | ||
*/ | ||
beagle_pwm_init(BBB_PWMSS0); | ||
|
||
float PWM_HZ = 7.0f ; /* 7 Hz */ | ||
float duty_A = 20.0f ; /* 20% Duty cycle for PWM 0_A output */ | ||
const float duty_B = 50.0f ; /* 50% Duty cycle for PWM 0_B output*/ | ||
|
||
/*Note: Always check whether pwmss clocks are enabled or not before configuring PWM*/ | ||
bool is_running = beagle_pwmss_is_running(BBB_PWMSS2); | ||
|
||
if(is_running) { | ||
|
||
/*To analyse the two different duty cycle Output should be observed at P8_45 and P8_46 pin number */ | ||
beagle_pwm_configure(BBB_PWMSS0, PWM_HZ ,duty_A , duty_B); | ||
printf("PWM enable for 10s ....\n"); | ||
|
||
/*Set Up counter and enable pwm module */ | ||
beagle_pwm_enable(BBB_PWMSS0); | ||
delay_sec(10); | ||
|
||
/*freeze the counter and disable pwm module*/ | ||
beagle_epwm_disable(BBB_PWMSS0); | ||
} | ||
} | ||
|
||
/* NOTICE: the clock driver is enabled */ | ||
#define CONFIGURE_APPLICATION_NEEDS_CLOCK_DRIVER | ||
#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER | ||
|
||
#define CONFIGURE_MAXIMUM_TASKS 1 | ||
#define CONFIGURE_USE_DEVFS_AS_BASE_FILESYSTEM | ||
|
||
#define CONFIGURE_MAXIMUM_SEMAPHORES 1 | ||
|
||
#define CONFIGURE_RTEMS_INIT_TASKS_TABLE | ||
|
||
#define CONFIGURE_EXTRA_TASK_STACKS (2 * RTEMS_MINIMUM_STACK_SIZE) | ||
|
||
#define CONFIGURE_INITIAL_EXTENSIONS RTEMS_TEST_INITIAL_EXTENSION | ||
|
||
#define CONFIGURE_INIT | ||
#include <rtems/confdefs.h> | ||
|
Oops, something went wrong.