RTEMS 6.1-rc7
Loading...
Searching...
No Matches
PWM

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";
static void inline delay_sec(int sec)
{
}
)
{
printf("Starting PWM Testing");
/*Initialize GPIO pins in BBB*/
/* 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);
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>
BeagleBone Black PWM support definitions.
bool beagle_pwm_enable(BBB_PWMSS pwmid)
This API enables the particular PWM module.
bool beagle_pwmss_is_running(unsigned int pwmss_id)
This function determines whether PWMSS-wide clocks enabled or not.
bool beagle_pwm_init(BBB_PWMSS pwmss_id)
BeagleBone Black PWM API.
This header file evaluates the application configuration options defined by the application.
RTEMS GPIO API definition.
rtems_status_code rtems_gpio_initialize(void)
Initializes the GPIO API.
Definition: gpio-support.c:640
#define rtems_clock_get_ticks_per_second()
Gets the number of clock ticks per second configured for the application.
Definition: clock.h:871
rtems_status_code rtems_task_wake_after(rtems_interval ticks)
Wakes up after a count of clock ticks have occurred or yields the processor.
Definition: taskwakeafter.c:46
void rtems_task
This type defines the return type of task entry points.
Definition: tasks.h:230
CPU_Uint32ptr rtems_task_argument
This integer type represents task argument values.
Definition: tasks.h:100
rtems_printer rtems_test_printer
Provides an RTEMS printer for tests.
Definition: testprinter.c:44
const char rtems_test_name[]
Each test must define a test name string.
Definition: init.c:6899
int rtems_test_begin(const char *name, const RTEMS_TEST_STATE state)
Prints a begin of test message using printf().
Definition: testbeginend.c:56
Definition: printer.h:76
This header file provides interfaces of the RTEMS Test Framework.