forked from Imagelibrary/rtems
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
This commit is contained in:
@@ -3,11 +3,11 @@
|
||||
*
|
||||
* @ingroup arm_beagle
|
||||
*
|
||||
* @brief BeagleBone Black BSP definitions.
|
||||
* @brief BeagleBone Black PWM support definitions.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright (c) 2016 Punit Vara <punitvara at gmail.com>
|
||||
* Copyright (c) 2016 Punit Vara <punitvara@gmail.com>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
@@ -31,43 +31,53 @@ extern "C" {
|
||||
#define BBB_CONTROL_CONF_GPMC_AD(n) (0x800 + (n * 4))
|
||||
#define BBB_CONTROL_CONF_LCD_DATA(n) (0x8a0 + (n * 4))
|
||||
|
||||
#define BBB_PWMSS_COUNT 3
|
||||
#define BBB_PWMSS0 0
|
||||
#define BBB_PWMSS1 1
|
||||
#define BBB_PWMSS2 2
|
||||
/**
|
||||
* @brief The set of possible PWM subsystem module
|
||||
*
|
||||
* Enumerated type to define various instance of pwm module.
|
||||
*/
|
||||
typedef enum{
|
||||
BBB_PWMSS0 = 0,
|
||||
BBB_PWMSS1,
|
||||
BBB_PWMSS2,
|
||||
BBB_PWMSS_COUNT
|
||||
}BBB_PWMSS;
|
||||
|
||||
#define BBB_P8_13_2B 3
|
||||
#define BBB_P8_19_2A 4
|
||||
#define BBB_P8_45_2A 5
|
||||
#define BBB_P8_46_2B 6
|
||||
#define BBB_P8_34_1B 7
|
||||
#define BBB_P8_36_1A 8
|
||||
#define BBB_P9_14_1A 9
|
||||
#define BBB_P9_16_1B 10
|
||||
#define BBB_P9_21_0B 11
|
||||
#define BBB_P9_22_0A 12
|
||||
#define BBB_P9_29_0B 13
|
||||
#define BBB_P9_31_0A 14
|
||||
typedef enum{
|
||||
BBB_P8_13_2B = 3,
|
||||
BBB_P8_19_2A,
|
||||
BBB_P8_45_2A,
|
||||
BBB_P8_46_2B,
|
||||
BBB_P8_34_1B,
|
||||
BBB_P8_36_1A,
|
||||
BBB_P9_14_1A,
|
||||
BBB_P9_16_1B,
|
||||
BBB_P9_21_0B,
|
||||
BBB_P9_22_0A,
|
||||
BBB_P9_29_0B,
|
||||
BBB_P9_31_0A
|
||||
}bbb_pwm_pin_t;
|
||||
|
||||
#define BBB_MUX0 0
|
||||
#define BBB_MUX1 1
|
||||
#define BBB_MUX2 2
|
||||
#define BBB_MUX3 3
|
||||
#define BBB_MUX4 4
|
||||
#define BBB_MUX5 5
|
||||
#define BBB_MUX6 6
|
||||
#define BBB_MUX7 7
|
||||
|
||||
#define BBB_EPWM1 1
|
||||
#define BBB_EPWM2 2
|
||||
#define BBB_EPWM0 0
|
||||
#define BBB_P8_13_MUX_PWM 4
|
||||
#define BBB_P8_19_MUX_PWM 4
|
||||
#define BBB_P8_45_MUX_PWM 3
|
||||
#define BBB_P8_46_MUX_PWM 3
|
||||
#define BBB_P8_34_MUX_PWM 2
|
||||
#define BBB_P8_36_MUX_PWM 2
|
||||
#define BBB_P9_14_MUX_PWM 6
|
||||
#define BBB_P9_16_MUX_PWM 6
|
||||
#define BBB_P9_21_MUX_PWM 3
|
||||
#define BBB_P9_22_MUX_PWM 3
|
||||
#define BBB_P9_29_MUX_PWM 1
|
||||
#define BBB_P9_31_MUX_PWM 1
|
||||
#define BBB_PWM_FREQ_THRESHOLD 0.5f
|
||||
|
||||
/**
|
||||
* @brief BeagleBone Black PWM API.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief This function intilize clock and pinmuxing for pwm sub system.
|
||||
* @brief This function intilizes clock for pwm sub system.
|
||||
*
|
||||
* @param PWMSS_ID It is the instance number of EPWM of pwm sub system.
|
||||
*
|
||||
@@ -75,20 +85,20 @@ extern "C" {
|
||||
* @return false if not successful
|
||||
*
|
||||
**/
|
||||
bool beagle_pwm_init(uint32_t pwmss_id);
|
||||
bool beagle_pwm_init(BBB_PWMSS pwmss_id);
|
||||
|
||||
/* PWMSS setting
|
||||
* set pulse argument of epwm module
|
||||
*
|
||||
* @param pwm_id : EPWMSS number , 0~2
|
||||
* @param pwm_freq : frequency to be generated
|
||||
* @param dutyA : Duty Cycle in ePWM A
|
||||
* @param dutyB : Duty Cycle in ePWM B
|
||||
* @param dutyA : Duty Cycle(in percentage) in PWM channel A
|
||||
* @param dutyB : Duty Cycle(in percentage) in PWM channel B
|
||||
*
|
||||
* @return : 1 for success
|
||||
* @return : 0 for failed
|
||||
*
|
||||
* @example : PWMSS_Setting(0 , 50.0f , 50.0f , 25.0f); // Generate 50HZ pwm in PWM0 ,
|
||||
* @example : beagle_pwm_configure(0 , 50.0f , 50.0f , 25.0f); // Generate 50HZ pwm in PWM0 ,
|
||||
* // duty cycle is 50% for ePWM0A , 25% for ePWM0B
|
||||
*
|
||||
* @Note :
|
||||
@@ -105,12 +115,12 @@ bool beagle_pwm_init(uint32_t pwmss_id);
|
||||
* Divisor = CLKDIV * HSPCLKDIV
|
||||
* 1 TBPRD : 10 ns (default)
|
||||
* 65535 TBPRD : 655350 ns
|
||||
* 65535 TBPRD : 655350 * Divisor ns = X TBPRD : Cyclens
|
||||
* 65535 TBPRD : 655350 * Divisor ns = X TBPRD : Cycle
|
||||
*
|
||||
* accrooding to that , we must find a Divisor value , let X nearest 65535 .
|
||||
* so , Divisor must Nearest Cyclens/655350
|
||||
* so , Divisor must Nearest Cycle/655350
|
||||
*/
|
||||
int beagle_pwmss_setting(uint32_t pwm_id, float pwm_freq, float dutyA, float dutyB);
|
||||
int beagle_pwm_configure(BBB_PWMSS pwm_id, float pwm_freq, float duty_a, float duty_b);
|
||||
|
||||
/**
|
||||
* @brief This API enables the particular PWM module.
|
||||
@@ -121,10 +131,10 @@ int beagle_pwmss_setting(uint32_t pwm_id, float pwm_freq, float dutyA, float dut
|
||||
* @return false if fail
|
||||
*
|
||||
**/
|
||||
bool beagle_ehrpwm_enable(uint32_t pwmid);
|
||||
bool beagle_pwm_enable(BBB_PWMSS pwmid);
|
||||
|
||||
/**
|
||||
* @brief This API disables the HR sub-module.
|
||||
* @brief This API disables the particular PWM module.
|
||||
*
|
||||
* @param pwmid It is the instance number of EPWM of pwm sub system.
|
||||
*
|
||||
@@ -132,10 +142,10 @@ bool beagle_ehrpwm_enable(uint32_t pwmid);
|
||||
* @return false if fail
|
||||
*
|
||||
**/
|
||||
bool beagle_ehrpwm_disable(uint32_t pwmid);
|
||||
bool beagle_pwm_disable(BBB_PWMSS pwmid);
|
||||
|
||||
/**
|
||||
* @brief This function Enables pinmuxing for PWM module.
|
||||
* @brief This function enables pinmuxing for PWM module.
|
||||
*
|
||||
* @param pin_no It is individual pin at which freuqency need to be generated.
|
||||
* It should be according to pwm sub system.
|
||||
@@ -146,7 +156,20 @@ bool beagle_ehrpwm_disable(uint32_t pwmid);
|
||||
* @return false if fail
|
||||
*
|
||||
**/
|
||||
bool beagle_epwm_pinmux_setup(uint32_t pin_no, uint32_t pwm_id);
|
||||
bool beagle_pwm_pinmux_setup(bbb_pwm_pin_t pin_no, BBB_PWMSS pwm_id);
|
||||
|
||||
/**
|
||||
* @brief This function determines whether PWMSS-wide clocks enabled or not.
|
||||
*
|
||||
* @param pwmss_id It is the instance number of PWMSS which clocks need to be
|
||||
* checked.
|
||||
*
|
||||
* @return true if successful
|
||||
* @return false if fail
|
||||
*
|
||||
**/
|
||||
bool beagle_pwmss_is_running(unsigned int pwmss_id);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -118,6 +118,10 @@ $(PROJECT_INCLUDE)/bsp/bbb-gpio.h: include/bbb-gpio.h $(PROJECT_INCLUDE)/bsp/$(d
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/bbb-gpio.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/bbb-gpio.h
|
||||
|
||||
$(PROJECT_INCLUDE)/bsp/bbb-pwm.h: include/bbb-pwm.h $(PROJECT_INCLUDE)/bsp/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/bsp/bbb-pwm.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/bsp/bbb-pwm.h
|
||||
|
||||
$(PROJECT_INCLUDE)/libcpu/arm-cp15.h: ../../../libcpu/arm/shared/include/arm-cp15.h $(PROJECT_INCLUDE)/libcpu/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/libcpu/arm-cp15.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/libcpu/arm-cp15.h
|
||||
|
||||
197
c/src/lib/libbsp/arm/beagle/pwm/README
Normal file
197
c/src/lib/libbsp/arm/beagle/pwm/README
Normal file
@@ -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>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright (c) 2016 Punit Vara <punitvara at gmail.com>
|
||||
* Copyright (c) 2016 Punit Vara <punitvara@gmail.com>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
@@ -24,6 +24,7 @@
|
||||
#include <bsp/bbb-gpio.h>
|
||||
#include <bsp.h>
|
||||
#include <bsp/bbb-pwm.h>
|
||||
#include <bsp/beagleboneblack.h>
|
||||
|
||||
/* Currently these definitions are for BeagleBone Black board only
|
||||
* Later on Beagle-xM board support can be added in this code.
|
||||
@@ -32,102 +33,97 @@
|
||||
#if IS_AM335X
|
||||
|
||||
/*
|
||||
* @brief This function select PWM module to be enabled
|
||||
* @brief This function selects EPWM module to be enabled
|
||||
*
|
||||
* @param pwm_id It is the instance number of EPWM of pwm sub system.
|
||||
*
|
||||
* @return Base Address of respective pwm instant.
|
||||
*/
|
||||
static uint32_t select_pwmss(uint32_t pwm_id)
|
||||
static uint32_t select_pwm(BBB_PWMSS pwm_id)
|
||||
{
|
||||
uint32_t baseAddr=0;
|
||||
if (pwm_id == BBB_PWMSS0)
|
||||
{
|
||||
|
||||
if (pwm_id == BBB_PWMSS0) {
|
||||
baseAddr = AM335X_EPWM_0_REGS;
|
||||
return baseAddr;
|
||||
}
|
||||
else if (pwm_id == BBB_PWMSS1)
|
||||
{
|
||||
} else if (pwm_id == BBB_PWMSS1) {
|
||||
baseAddr = AM335X_EPWM_1_REGS;
|
||||
return baseAddr;
|
||||
}
|
||||
else if (pwm_id == BBB_PWMSS2)
|
||||
{
|
||||
} else if (pwm_id == BBB_PWMSS2) {
|
||||
baseAddr = AM335X_EPWM_2_REGS;
|
||||
} else {
|
||||
baseAddr = 0;
|
||||
}
|
||||
return baseAddr;
|
||||
}
|
||||
else
|
||||
|
||||
/*
|
||||
* @brief This function selects PWM Sub system to be enabled
|
||||
*
|
||||
* @param pwmss_id The instance number of ePWMSS whose system clocks
|
||||
* have to be configured.
|
||||
*
|
||||
* @return Base Address of respective pwmss instant.
|
||||
*/
|
||||
static uint32_t select_pwmss(BBB_PWMSS pwmss_id)
|
||||
{
|
||||
printf("Invalid PWM Id\n");
|
||||
return 0;
|
||||
uint32_t baseAddr=0;
|
||||
|
||||
if (pwmss_id == BBB_PWMSS0) {
|
||||
baseAddr = AM335X_PWMSS0_MMAP_ADDR;
|
||||
} else if (pwmss_id == BBB_PWMSS1) {
|
||||
baseAddr = AM335X_PWMSS1_MMAP_ADDR;
|
||||
} else if (pwmss_id == BBB_PWMSS2) {
|
||||
baseAddr = AM335X_PWMSS2_MMAP_ADDR;
|
||||
} else {
|
||||
baseAddr = 0;
|
||||
}
|
||||
return baseAddr;
|
||||
}
|
||||
|
||||
bool beagle_epwm_pinmux_setup(uint32_t pin_no, uint32_t pwm_id)
|
||||
bool beagle_pwm_pinmux_setup(bbb_pwm_pin_t pin_no, BBB_PWMSS pwm_id)
|
||||
{
|
||||
switch(pwm_id) {
|
||||
case BBB_PWMSS2:
|
||||
switch(pin_no) {
|
||||
case BBB_P8_13_2B:
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(9)) = BBB_MUXMODE(BBB_MUX4);
|
||||
break;
|
||||
case BBB_P8_19_2A:
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(8)) = BBB_MUXMODE(BBB_MUX4);
|
||||
break;
|
||||
case BBB_P8_45_2A:
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(0)) = BBB_MUXMODE(BBB_MUX3);
|
||||
break;
|
||||
case BBB_P8_46_2B:
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(1)) = BBB_MUXMODE(BBB_MUX3);
|
||||
break;
|
||||
default :
|
||||
printf("Invalid pin for module 2\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case BBB_PWMSS1:
|
||||
switch(pin_no) {
|
||||
case BBB_P8_34_1B:
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(11)) = BBB_MUXMODE(BBB_MUX2);
|
||||
break;
|
||||
case BBB_P8_36_1A:
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(10)) = BBB_MUXMODE(BBB_MUX2);
|
||||
break;
|
||||
case BBB_P9_14_1A:
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(2)) = BBB_MUXMODE(BBB_MUX6);
|
||||
break;
|
||||
case BBB_P9_16_1B:
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(3)) = BBB_MUXMODE(BBB_MUX6);
|
||||
break;
|
||||
default :
|
||||
printf("Invalid pin for module 1\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case BBB_PWMSS0:
|
||||
switch(pin_no) {
|
||||
case BBB_P9_21_0B:
|
||||
REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_D0) = BBB_MUXMODE(BBB_MUX3);
|
||||
break;
|
||||
case BBB_P9_22_0A:
|
||||
REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_SCLK) = BBB_MUXMODE(BBB_MUX3);
|
||||
break;
|
||||
case BBB_P9_29_0B:
|
||||
REG(AM335X_PADCONF_BASE + AM335X_CONF_MCASP0_FSX) = BBB_MUXMODE(BBB_MUX1);
|
||||
break;
|
||||
case BBB_P9_31_0A:
|
||||
REG(AM335X_PADCONF_BASE + AM335X_CONF_MCASP0_ACLKX) = BBB_MUXMODE(BBB_MUX1);
|
||||
break;
|
||||
default:
|
||||
printf("Invalid pin for module 0\n");
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
bool is_valid = true;
|
||||
|
||||
default:
|
||||
printf("Invalid PWM sub system\n");
|
||||
return false;
|
||||
if(pwm_id == BBB_PWMSS0) {
|
||||
if (pin_no == BBB_P9_21_0B) {
|
||||
REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_D0) = BBB_MUXMODE(BBB_P9_21_MUX_PWM);
|
||||
} else if (pin_no == BBB_P9_22_0A) {
|
||||
REG(AM335X_PADCONF_BASE + AM335X_CONF_SPI0_SCLK) = BBB_MUXMODE(BBB_P9_22_MUX_PWM);
|
||||
} else if (pin_no == BBB_P9_29_0B) {
|
||||
REG(AM335X_PADCONF_BASE + AM335X_CONF_MCASP0_FSX) = BBB_MUXMODE(BBB_P9_29_MUX_PWM);
|
||||
} else if (pin_no == BBB_P9_31_0A) {
|
||||
REG(AM335X_PADCONF_BASE + AM335X_CONF_MCASP0_ACLKX) = BBB_MUXMODE(BBB_P9_31_MUX_PWM);
|
||||
} else {
|
||||
is_valid = false;
|
||||
}
|
||||
|
||||
} else if (pwm_id == BBB_PWMSS1) {
|
||||
if (pin_no == BBB_P8_34_1B) {
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(11)) = BBB_MUXMODE(BBB_P8_34_MUX_PWM);
|
||||
} else if (pin_no == BBB_P8_36_1A) {
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(10)) = BBB_MUXMODE(BBB_P8_36_MUX_PWM);
|
||||
} else if (pin_no == BBB_P9_14_1A) {
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(2)) = BBB_MUXMODE(BBB_P9_14_MUX_PWM);
|
||||
} else if (pin_no == BBB_P9_16_1B) {
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(3)) = BBB_MUXMODE(BBB_P9_16_MUX_PWM);
|
||||
} else {
|
||||
is_valid = false;
|
||||
}
|
||||
} else if (pwm_id == BBB_PWMSS2) {
|
||||
if (pin_no == BBB_P8_13_2B) {
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(9)) = BBB_MUXMODE(BBB_P8_13_MUX_PWM);
|
||||
} else if (pin_no == BBB_P8_19_2A) {
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_GPMC_AD(8)) = BBB_MUXMODE(BBB_P8_19_MUX_PWM);
|
||||
} else if (pin_no == BBB_P8_45_2A) {
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(0)) = BBB_MUXMODE(BBB_P8_45_MUX_PWM);
|
||||
} else if (pin_no == BBB_P8_46_2B) {
|
||||
REG(AM335X_PADCONF_BASE + BBB_CONTROL_CONF_LCD_DATA(1)) = BBB_MUXMODE(BBB_P8_46_MUX_PWM);
|
||||
} else {
|
||||
is_valid = false;
|
||||
}
|
||||
} else {
|
||||
is_valid = false;
|
||||
}
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -137,26 +133,20 @@ bool beagle_epwm_pinmux_setup(uint32_t pin_no, uint32_t pwm_id)
|
||||
* @param instance It is the instance number of EPWM of pwmsubsystem.
|
||||
*
|
||||
* @return true if successful
|
||||
* false if unsuccessful
|
||||
**/
|
||||
static bool pwmss_tbclk_enable(unsigned int instance)
|
||||
static bool pwmss_tbclk_enable(BBB_PWMSS instance)
|
||||
{
|
||||
uint32_t enable_bit;
|
||||
bool is_valid = true;
|
||||
|
||||
if (instance == BBB_PWMSS0)
|
||||
{
|
||||
if (instance == BBB_PWMSS0) {
|
||||
enable_bit = AM335X_PWMSS_CTRL_PWMSS0_TBCLKEN;
|
||||
}
|
||||
else if (instance == BBB_PWMSS1)
|
||||
{
|
||||
} else if (instance == BBB_PWMSS1) {
|
||||
enable_bit = AM335X_PWMSS_CTRL_PWMSS1_TBCLKEN;
|
||||
}
|
||||
else if (instance == BBB_PWMSS2)
|
||||
{
|
||||
} else if (instance == BBB_PWMSS2) {
|
||||
enable_bit = AM335X_PWMSS_CTRL_PWMSS2_TBCLKEN;
|
||||
}
|
||||
else
|
||||
{
|
||||
} else {
|
||||
is_valid = false;
|
||||
}
|
||||
|
||||
@@ -173,18 +163,22 @@ bool is_valid = true;
|
||||
*
|
||||
* @param pwm_id It is the instance number of EPWM of pwm sub system.
|
||||
*
|
||||
* @return None.
|
||||
* @return true if successful
|
||||
* false if unsuccessful
|
||||
*
|
||||
**/
|
||||
static void epwm_clock_enable(uint32_t pwm_id)
|
||||
static bool pwm_clock_enable(BBB_PWMSS pwm_id)
|
||||
{
|
||||
if((pwm_id <3) && (pwm_id >=0)) {
|
||||
uint32_t baseAddr;
|
||||
baseAddr = select_pwmss(pwm_id);
|
||||
REG(baseAddr - AM335X_EPWM_REGS + AM335X_PWMSS_CLKCONFIG) |= AM335X_PWMSS_CLK_EN_ACK;
|
||||
const bool id_is_valid = pwm_id < BBB_PWMSS_COUNT;
|
||||
bool status = true;
|
||||
|
||||
if (id_is_valid) {
|
||||
const uint32_t baseAddr = select_pwmss(pwm_id);
|
||||
REG(baseAddr + AM335X_PWMSS_CLKCONFIG) |= AM335X_PWMSS_CLK_EN_ACK;
|
||||
} else {
|
||||
printf("Invalid pwm_id\n");
|
||||
status = false;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -198,184 +192,230 @@ static void epwm_clock_enable(uint32_t pwm_id)
|
||||
* 'pwmss_id' can take one of the following values:
|
||||
* (0 <= pwmss_id <= 2)
|
||||
*
|
||||
* @return None.
|
||||
*
|
||||
* @return True if successful
|
||||
* False if Unsuccessful
|
||||
*/
|
||||
static void module_clk_config(uint32_t pwmss_id)
|
||||
static bool pwmss_module_clk_config(BBB_PWMSS pwmss_id)
|
||||
{
|
||||
if(pwmss_id == 0)
|
||||
{
|
||||
REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS0_CLKCTRL) |=
|
||||
AM335X_CM_PER_EPWMSS0_CLKCTRL_MODULEMODE_ENABLE;
|
||||
bool is_valid = true;
|
||||
|
||||
while(AM335X_CM_PER_EPWMSS0_CLKCTRL_MODULEMODE_ENABLE !=
|
||||
(REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS0_CLKCTRL) &
|
||||
AM335X_CM_PER_EPWMSS0_CLKCTRL_MODULEMODE));
|
||||
if(pwmss_id == BBB_PWMSS0) {
|
||||
const uint32_t is_functional = AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST_FUNC <<
|
||||
AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST_SHIFT;
|
||||
const uint32_t clkctrl = AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS0_CLKCTRL;
|
||||
const uint32_t idle_bits = AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST;
|
||||
const uint32_t is_enable = AM335X_CM_PER_EPWMSS0_CLKCTRL_MODULEMODE_ENABLE;
|
||||
const uint32_t module_mode = AM335X_CM_PER_EPWMSS0_CLKCTRL_MODULEMODE;
|
||||
|
||||
while((AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST_FUNC <<
|
||||
AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST_SHIFT) !=
|
||||
(REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS0_CLKCTRL) &
|
||||
AM335X_CM_PER_EPWMSS0_CLKCTRL_IDLEST));
|
||||
REG(clkctrl) |= is_enable;
|
||||
while((REG(clkctrl) & module_mode) != is_enable);
|
||||
while((REG(clkctrl) & idle_bits) != is_functional);
|
||||
}
|
||||
else if(pwmss_id == 1)
|
||||
{
|
||||
REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS1_CLKCTRL) |=
|
||||
AM335X_CM_PER_EPWMSS1_CLKCTRL_MODULEMODE_ENABLE;
|
||||
while(AM335X_CM_PER_EPWMSS1_CLKCTRL_MODULEMODE_ENABLE !=
|
||||
(REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS1_CLKCTRL) &
|
||||
AM335X_CM_PER_EPWMSS1_CLKCTRL_MODULEMODE));
|
||||
else if(pwmss_id == BBB_PWMSS1) {
|
||||
const uint32_t is_functional = AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST_FUNC <<
|
||||
AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST_SHIFT;
|
||||
const uint32_t clkctrl = AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS1_CLKCTRL;
|
||||
const uint32_t idle_bits = AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST;
|
||||
const uint32_t is_enable = AM335X_CM_PER_EPWMSS1_CLKCTRL_MODULEMODE_ENABLE;
|
||||
const uint32_t module_mode = AM335X_CM_PER_EPWMSS1_CLKCTRL_MODULEMODE;
|
||||
|
||||
while((AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST_FUNC <<
|
||||
AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST_SHIFT) !=
|
||||
(REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS1_CLKCTRL) &
|
||||
AM335X_CM_PER_EPWMSS1_CLKCTRL_IDLEST));
|
||||
}
|
||||
else if(pwmss_id == 2)
|
||||
{
|
||||
REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS2_CLKCTRL) |=
|
||||
AM335X_CM_PER_EPWMSS2_CLKCTRL_MODULEMODE_ENABLE;
|
||||
while(AM335X_CM_PER_EPWMSS2_CLKCTRL_MODULEMODE_ENABLE !=
|
||||
(REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS2_CLKCTRL) &
|
||||
AM335X_CM_PER_EPWMSS2_CLKCTRL_MODULEMODE));
|
||||
REG(clkctrl) |= is_enable;
|
||||
while((REG(clkctrl) & module_mode) != is_enable);
|
||||
while((REG(clkctrl) & idle_bits) != is_functional);
|
||||
} else if(pwmss_id == BBB_PWMSS2) {
|
||||
const uint32_t is_functional = AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST_FUNC <<
|
||||
AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST_SHIFT;
|
||||
const uint32_t clkctrl = AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS2_CLKCTRL;
|
||||
const uint32_t idle_bits = AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST;
|
||||
const uint32_t is_enable = AM335X_CM_PER_EPWMSS2_CLKCTRL_MODULEMODE_ENABLE;
|
||||
const uint32_t module_mode = AM335X_CM_PER_EPWMSS2_CLKCTRL_MODULEMODE;
|
||||
|
||||
while((AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST_FUNC <<
|
||||
AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST_SHIFT) !=
|
||||
(REG(AM335X_CM_PER_ADDR + AM335X_CM_PER_EPWMSS2_CLKCTRL) &
|
||||
AM335X_CM_PER_EPWMSS2_CLKCTRL_IDLEST));
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Please enter valid pwm Id \n");
|
||||
}
|
||||
REG(clkctrl) |= is_enable;
|
||||
while((REG(clkctrl) & module_mode) != is_enable);
|
||||
while((REG(clkctrl) & idle_bits) != is_functional);
|
||||
} else
|
||||
is_valid = false;
|
||||
return is_valid;
|
||||
}
|
||||
|
||||
bool beagle_pwm_init(uint32_t pwmss_id)
|
||||
bool beagle_pwm_init(BBB_PWMSS pwmss_id)
|
||||
{
|
||||
const bool id_is_valid = pwmss_id < BBB_PWMSS_COUNT;
|
||||
bool status = true;
|
||||
if((pwmss_id <3) && (pwmss_id >=0))
|
||||
{
|
||||
module_clk_config(pwmss_id);
|
||||
epwm_clock_enable(pwmss_id);
|
||||
|
||||
if(id_is_valid) {
|
||||
pwmss_module_clk_config(pwmss_id);
|
||||
pwm_clock_enable(pwmss_id);
|
||||
pwmss_tbclk_enable(pwmss_id);
|
||||
return status;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
status =false;
|
||||
return status;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
int beagle_pwmss_setting(uint32_t pwm_id, float pwm_freq, float dutyA, float dutyB)
|
||||
int beagle_pwm_configure(BBB_PWMSS pwm_id, float pwm_freq, float duty_a, float duty_b)
|
||||
{
|
||||
uint32_t baseAddr;
|
||||
int status = 1;
|
||||
|
||||
if(pwm_freq <= 0.5) {
|
||||
status =0;
|
||||
return status;
|
||||
}
|
||||
if(dutyA < 0.0f || dutyA > 100.0f || dutyB < 0.0f || dutyB > 100.0f) {
|
||||
status = 0;
|
||||
return status;
|
||||
}
|
||||
dutyA /= 100.0f;
|
||||
dutyB /= 100.0f;
|
||||
|
||||
/*Compute necessary TBPRD*/
|
||||
float Cyclens = 0.0f;
|
||||
float Divisor =0;
|
||||
int i,j;
|
||||
float cycle = 0.0f,divisor = 0;
|
||||
unsigned int i,j;
|
||||
const float CLKDIV_div[] = {1.0,2.0,4.0,8.0,16.0,32.0,64.0,128.0};
|
||||
const float HSPCLKDIV_div[] = {1.0, 2.0, 4.0, 6.0, 8.0, 10.0,12.0, 14.0};
|
||||
int NearCLKDIV =7;
|
||||
int NearHSPCLKDIV =7;
|
||||
int NearTBPRD =0;
|
||||
int NearCLKDIV =7,NearHSPCLKDIV =7,NearTBPRD =0;
|
||||
|
||||
if (pwm_freq <= BBB_PWM_FREQ_THRESHOLD) {
|
||||
status =0;
|
||||
}
|
||||
|
||||
if (duty_a < 0.0f || duty_a > 100.0f || duty_b < 0.0f || duty_b > 100.0f) {
|
||||
status = 0;
|
||||
}
|
||||
duty_a /= 100.0f;
|
||||
duty_b /= 100.0f;
|
||||
|
||||
/** 10^9 /Hz compute time per cycle (ns) */
|
||||
Cyclens = 1000000000.0f / pwm_freq;
|
||||
cycle = 1000000000.0f / pwm_freq;
|
||||
|
||||
/** am335x provide (128* 14) divider and per TBPRD means 10ns when divider
|
||||
* and max TBPRD is 65535 so max cycle is 128 * 8 * 14 * 65535 * 10ns */
|
||||
Divisor = (Cyclens / 655350.0f);
|
||||
|
||||
if(Divisor > (128 * 14)) {
|
||||
printf("Can't generate %f HZ",pwm_freq);
|
||||
divisor = (cycle / 655350.0f);
|
||||
if (divisor > (128 * 14)) {
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
for (i=0;i<8;i++) {
|
||||
for(j=0 ; j<8; j++) {
|
||||
if((CLKDIV_div[i] * HSPCLKDIV_div[j]) < (CLKDIV_div[NearCLKDIV]
|
||||
* HSPCLKDIV_div[NearHSPCLKDIV]) && (CLKDIV_div[i] * HSPCLKDIV_div[j] > Divisor)) {
|
||||
* HSPCLKDIV_div[NearHSPCLKDIV]) && (CLKDIV_div[i] * HSPCLKDIV_div[j] > divisor)) {
|
||||
NearCLKDIV = i;
|
||||
NearHSPCLKDIV = j;
|
||||
}
|
||||
}
|
||||
}
|
||||
baseAddr = select_pwmss(pwm_id);
|
||||
|
||||
baseAddr = select_pwm(pwm_id);
|
||||
|
||||
REG16(baseAddr + AM335X_EPWM_TBCTL) &= ~(AM335X_TBCTL_CLKDIV_MASK | AM335X_TBCTL_HSPCLKDIV_MASK);
|
||||
|
||||
REG16(baseAddr + AM335X_EPWM_TBCTL) = (REG16(baseAddr + AM335X_EPWM_TBCTL) &
|
||||
(~AM335X_EPWM_TBCTL_CLKDIV)) | ((NearCLKDIV
|
||||
const uint16_t clkdiv_clear = (REG16(baseAddr + AM335X_EPWM_TBCTL) &
|
||||
(~AM335X_EPWM_TBCTL_CLKDIV));
|
||||
const uint16_t clkdiv_write = ((NearCLKDIV
|
||||
<< AM335X_EPWM_TBCTL_CLKDIV_SHIFT) & AM335X_EPWM_TBCTL_CLKDIV);
|
||||
|
||||
REG16(baseAddr + AM335X_EPWM_TBCTL) = (REG16(baseAddr + AM335X_EPWM_TBCTL) &
|
||||
(~AM335X_EPWM_TBCTL_HSPCLKDIV)) | ((NearHSPCLKDIV <<
|
||||
REG16(baseAddr + AM335X_EPWM_TBCTL) = clkdiv_clear | clkdiv_write;
|
||||
const uint16_t hspclkdiv_clear = (REG16(baseAddr + AM335X_EPWM_TBCTL) &
|
||||
(~AM335X_EPWM_TBCTL_HSPCLKDIV));
|
||||
const uint16_t hspclkdiv_write = ((NearHSPCLKDIV <<
|
||||
AM335X_EPWM_TBCTL_HSPCLKDIV_SHIFT) & AM335X_EPWM_TBCTL_HSPCLKDIV);
|
||||
|
||||
NearTBPRD = (Cyclens / (10.0 * CLKDIV_div[NearCLKDIV] * HSPCLKDIV_div[NearHSPCLKDIV]));
|
||||
|
||||
REG16(baseAddr + AM335X_EPWM_TBCTL) = (REG16(baseAddr + AM335X_EPWM_TBCTL) &
|
||||
(~AM335X_EPWM_PRD_LOAD_SHADOW_MASK)) | (((bool)AM335X_EPWM_SHADOW_WRITE_DISABLE <<
|
||||
REG16(baseAddr + AM335X_EPWM_TBCTL) = hspclkdiv_clear | hspclkdiv_write;
|
||||
NearTBPRD = (cycle / (10.0 * CLKDIV_div[NearCLKDIV] * HSPCLKDIV_div[NearHSPCLKDIV]));
|
||||
const uint16_t shadow_mask = (REG16(baseAddr + AM335X_EPWM_TBCTL) &
|
||||
(~AM335X_EPWM_PRD_LOAD_SHADOW_MASK));
|
||||
const uint16_t shadow_disable = (((bool)AM335X_EPWM_SHADOW_WRITE_DISABLE <<
|
||||
AM335X_EPWM_TBCTL_PRDLD_SHIFT) & AM335X_EPWM_PRD_LOAD_SHADOW_MASK);
|
||||
|
||||
REG16(baseAddr + AM335X_EPWM_TBCTL) = (REG16(baseAddr + AM335X_EPWM_TBCTL) &
|
||||
(~AM335X_EPWM_COUNTER_MODE_MASK)) | (((unsigned int)AM335X_EPWM_COUNT_UP <<
|
||||
REG16(baseAddr + AM335X_EPWM_TBCTL) = shadow_mask | shadow_disable;
|
||||
const uint16_t counter_mask = (REG16(baseAddr + AM335X_EPWM_TBCTL) &
|
||||
(~AM335X_EPWM_COUNTER_MODE_MASK));
|
||||
const uint16_t counter_shift = (((unsigned int)AM335X_EPWM_COUNT_UP <<
|
||||
AM335X_TBCTL_CTRMODE_SHIFT) & AM335X_EPWM_COUNTER_MODE_MASK);
|
||||
|
||||
REG16(baseAddr + AM335X_EPWM_TBCTL) = counter_mask | counter_shift;
|
||||
/*setting clock divider and freeze time base*/
|
||||
REG16(baseAddr + AM335X_EPWM_CMPB) = (unsigned short)((float)(NearTBPRD) * dutyB);
|
||||
REG16(baseAddr + AM335X_EPWM_CMPA) = (unsigned short)((float)(NearTBPRD) * dutyA);
|
||||
REG16(baseAddr + AM335X_EPWM_CMPB) = (unsigned short)((float)(NearTBPRD) * duty_b);
|
||||
REG16(baseAddr + AM335X_EPWM_CMPA) = (unsigned short)((float)(NearTBPRD) * duty_a);
|
||||
REG16(baseAddr + AM335X_EPWM_TBPRD) = (unsigned short)NearTBPRD;
|
||||
REG16(baseAddr + AM335X_EPWM_TBCNT) = 0;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
bool beagle_ehrpwm_enable(uint32_t pwmid)
|
||||
bool beagle_pwm_enable(BBB_PWMSS pwmid)
|
||||
{
|
||||
const bool id_is_valid = pwmid < BBB_PWMSS_COUNT;
|
||||
bool status = true;
|
||||
uint32_t baseAddr;
|
||||
if((pwmid<3) && (pwmid >=0)) {
|
||||
baseAddr = select_pwmss(pwmid);
|
||||
|
||||
if (id_is_valid) {
|
||||
const uint32_t baseAddr = select_pwm(pwmid);
|
||||
/* Initially set EPWMxA o/p high , when increasing counter = CMPA toggle o/p of EPWMxA */
|
||||
REG16(baseAddr + AM335X_EPWM_AQCTLA) = AM335X_EPWM_AQCTLA_ZRO_XAHIGH | (AM335X_EPWM_AQCTLA_CAU_EPWMXATOGGLE << AM335X_EPWM_AQCTLA_CAU_SHIFT);
|
||||
/* Initially set EPWMxB o/p high , when increasing counter = CMPA toggle o/p of EPWMxB */
|
||||
REG16(baseAddr + AM335X_EPWM_AQCTLB) = AM335X_EPWM_AQCTLB_ZRO_XBHIGH | (AM335X_EPWM_AQCTLB_CBU_EPWMXBTOGGLE << AM335X_EPWM_AQCTLB_CBU_SHIFT);
|
||||
REG16(baseAddr + AM335X_EPWM_TBCNT) = 0;
|
||||
/* Set counter mode : Up-count mode */
|
||||
REG16(baseAddr + AM335X_EPWM_TBCTL) |= AM335X_TBCTL_FREERUN | AM335X_TBCTL_CTRMODE_UP;
|
||||
return status;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
status =false;
|
||||
return status;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
bool beagle_ehrpwm_disable(uint32_t pwmid)
|
||||
bool beagle_pwm_disable(BBB_PWMSS pwmid)
|
||||
{
|
||||
const bool id_is_valid = pwmid < BBB_PWMSS_COUNT;
|
||||
bool status = true;
|
||||
uint32_t baseAddr;
|
||||
if((pwmid<3) && (pwmid >=0)) {
|
||||
baseAddr = select_pwmss(pwmid);
|
||||
|
||||
if (id_is_valid) {
|
||||
const uint32_t baseAddr = select_pwm(pwmid);
|
||||
REG16(baseAddr + AM335X_EPWM_TBCTL) = AM335X_EPWM_TBCTL_CTRMODE_STOPFREEZE;
|
||||
REG16(baseAddr + AM335X_EPWM_AQCTLA) = AM335X_EPWM_AQCTLA_ZRO_XALOW | (AM335X_EPWM_AQCTLA_CAU_EPWMXATOGGLE << AM335X_EPWM_AQCTLA_CAU_SHIFT);
|
||||
REG16(baseAddr + AM335X_EPWM_AQCTLB) = AM335X_EPWM_AQCTLA_ZRO_XBLOW | (AM335X_EPWM_AQCTLB_CBU_EPWMXBTOGGLE << AM335X_EPWM_AQCTLB_CBU_SHIFT);
|
||||
REG16(baseAddr + AM335X_EPWM_TBCNT) = 0;
|
||||
return status;
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
status = false;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This functions determines whether time base clock is enabled for EPWMSS
|
||||
*
|
||||
* @param pwmss_id The instance number of ePWMSS whose time base clock need to
|
||||
* be checked
|
||||
*
|
||||
* @return returns 4 for PWMSS_ID = 2
|
||||
* returns 2 for PWMSS_ID = 1
|
||||
* returns 1 for PWMSS_ID = 0
|
||||
**/
|
||||
static int pwmss_tb_clock_check(unsigned int pwmss_id)
|
||||
{
|
||||
unsigned int reg_value;
|
||||
|
||||
/*control module check*/
|
||||
reg_value = REG(AM335X_CONTROL_MODULE + AM335X_PWMSS_CTRL);
|
||||
return (reg_value & (1 << pwmss_id));
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief This functions determines whether clock for EPWMSS is enabled or not.
|
||||
*
|
||||
* @param It is the Memory address of the PWMSS instance used.
|
||||
*
|
||||
* @return
|
||||
*
|
||||
**/
|
||||
static unsigned int pwmss_clock_en_status(unsigned int pwmid)
|
||||
{
|
||||
unsigned int status;
|
||||
const uint32_t baseAddr = select_pwmss(pwmid);
|
||||
|
||||
status = REG(baseAddr + AM335X_PWMSS_CLKSTATUS);
|
||||
status = status >> 8 & 0x1;
|
||||
return status;
|
||||
}
|
||||
|
||||
bool beagle_pwmss_is_running(unsigned int pwmss_id)
|
||||
{
|
||||
const bool id_is_valid = pwmss_id < BBB_PWMSS_COUNT;
|
||||
bool status=true;
|
||||
|
||||
if (id_is_valid) {
|
||||
status = pwmss_clock_en_status(pwmss_id);
|
||||
if(status){
|
||||
status = pwmss_tb_clock_check(pwmss_id);
|
||||
} else {
|
||||
status = false;
|
||||
}
|
||||
} else {
|
||||
status = false;
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -387,33 +427,28 @@ bool beagle_ehrpwm_disable(uint32_t pwmid)
|
||||
* GPIO API and to make the build successful.
|
||||
* Later on support can be added here.
|
||||
*/
|
||||
uint32_t select_pwmss(uint32_t pwm_id)
|
||||
bool beagle_pwm_init(BBB_PWMSS pwmss_id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool beagle_pwm_disable(BBB_PWMSS pwmid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool beagle_pwm_enable(BBB_PWMSS pwmid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int beagle_pwm_configure(BBB_PWMSS pwm_id, float pwm_freq, float duty_a, float duty_b)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
bool pwmss_tbclk_enable(unsigned int instance)
|
||||
bool beagle_pwm_pinmux_setup(bbb_pwm_pin_t pin_no, BBB_PWMSS pwm_id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool beagle_pwm_init(uint32_t pwmss_id)
|
||||
bool beagle_pwmss_is_running(unsigned int pwmss_id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool beagle_ehrpwm_disable(uint32_t pwmid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool beagle_ehrpwm_enable(uint32_t pwmid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
int beagle_pwmss_setting(uint32_t pwm_id, float pwm_freq, float dutyA, float dutyB)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
bool beagle_epwm_pinmux_setup(uint32_t pin_no, uint32_t pwm_id)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user