This patch perform following things:
        - adds original BBBIO PWM code as it is.
        - not added to Makefile otherwise it will break build
        - adds required registers
        - adds declarations to BSP_HEADERS

        This code is added from
        
https://github.com/VegetableAvenger/BBBIOlib/blob/master/BBBio_lib/BBBiolib_PWMSS.c
---
 c/src/lib/libbsp/arm/beagle/include/bbb-pwm.h |  46 +++
 c/src/lib/libbsp/arm/beagle/pwm/pwm.c         | 407 ++++++++++++++++++++++++++
 c/src/lib/libcpu/arm/shared/include/am335x.h  |  11 +-
 3 files changed, 463 insertions(+), 1 deletion(-)
 create mode 100644 c/src/lib/libbsp/arm/beagle/include/bbb-pwm.h
 create mode 100644 c/src/lib/libbsp/arm/beagle/pwm/pwm.c

diff --git a/c/src/lib/libbsp/arm/beagle/include/bbb-pwm.h 
b/c/src/lib/libbsp/arm/beagle/include/bbb-pwm.h
new file mode 100644
index 0000000..bd70385
--- /dev/null
+++ b/c/src/lib/libbsp/arm/beagle/include/bbb-pwm.h
@@ -0,0 +1,46 @@
+/**
+ * @file
+ *
+ * @ingroup arm_beagle
+ *
+ * @brief BeagleBone Black BSP definitions.
+ */
+
+/**
+ * Copyright (c) 2016 Punit Vara <punitv...@gmail.com>
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rtems.org/license/LICENSE.
+ */
+
+#ifndef LIBBSP_ARM_BEAGLE_BBB_PWM_H
+#define LIBBSP_ARM_BEAGLE_BBB_PWM_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * @brief  BeagleBone Black PWM functions.
+ */
+#define BBBIO_PWMSS_COUNT       3
+#define BBBIO_PWMSS0           0
+#define BBBIO_PWMSS1           1  
+#define BBBIO_PWMSS2           2
+
+/**
+ * @brief  BeagleBone Black PWM API.
+ */
+int BBBIO_PWMSS_Setting(unsigned int PWMID , float HZ ,float dutyA ,float 
dutyB);   
+int BBBIO_PWM_Init();
+void BBBIO_PWM_Release();
+int BBBIO_PWMSS_Status(unsigned int PWMID);
+void BBBIO_ehrPWM_Enable(unsigned int PWMSS_ID);
+void BBBIO_ehrPWM_Disable(unsigned int PWMSS_ID);
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* LIBBSP_ARM_BEAGLE_BBB_PWM_H */
diff --git a/c/src/lib/libbsp/arm/beagle/pwm/pwm.c 
b/c/src/lib/libbsp/arm/beagle/pwm/pwm.c
new file mode 100644
index 0000000..f65ff89
--- /dev/null
+++ b/c/src/lib/libbsp/arm/beagle/pwm/pwm.c
@@ -0,0 +1,407 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <time.h>
+#include "BBBiolib.h"
+/*-----------------------------------------------------------------------------------------------*/
+/*
+ * PWMSS Registers
+ *
+ * @Source : AM335x Technical Reference Manual ,page 1991
+ *           Table 15-5. PWMSS REGISTERS
+ *
+*/
+
+#define PWMSS0_MMAP_ADDR       0x48300000
+#define PWMSS1_MMAP_ADDR       0x48302000
+#define PWMSS2_MMAP_ADDR       0x48304000
+#define PWMSS_MMAP_LEN         0x1000
+
+#define PWMSS_IDVER    0x0
+#define PWMSS_SYSCONFIG        0x4
+#define PWMSS_CLKCONFIG        0x8
+#define PWMSS_CLKSTATUS        0xC
+
+/* EPWM Registers
+ *
+ * @Source : AM335x Technical Reference Manual ,page 2084
+ *           Table 15-58. EPWM REGISTERS
+ *
+*/
+#define EPWM_TBCTL     0x0
+#define EPWM_TBSTS     0x2
+#define EPWM_TBPHSHR   0x4
+#define EPWM_TBPHS     0x6
+#define EPWM_TBCNT     0x8
+#define EPWM_TBPRD     0xA
+#define EPWM_CMPCTL    0xE
+#define EPWM_CMPAHR    0x10
+#define EPWM_CMPA      0x12
+#define EPWM_CMPB      0x14
+#define EPWM_AQCTLA    0x16
+#define EPWM_AQCTLB    0x18
+#define EPWM_AQSFRC    0x1A
+#define EPWM_AQCSFRC   0x1C
+#define EPWM_DBCTL     0x1E
+#define EPWM_DBRED     0x20
+#define EPWM_DBFED     0x22
+/*-----------------------------------------------------------------------------------------------*/
+extern int memh;
+extern volatile unsigned int *CM_ptr;  /*c ontrol module */
+volatile unsigned int *cm_per_addr;
+
+
+const unsigned int PWMSS_AddressOffset[]={PWMSS0_MMAP_ADDR,
+                                         PWMSS1_MMAP_ADDR,
+                                         PWMSS2_MMAP_ADDR};
+volatile unsigned int *pwmss_ptr[3]     ={NULL, NULL, NULL} ;
+volatile unsigned int *epwm_ptr[3]      ={NULL, NULL, NULL} ;
+volatile unsigned int *ecap_ptr[3]      ={NULL, NULL, NULL} ;
+volatile unsigned int *eqep_ptr[3]      ={NULL, NULL, NULL} ;
+
+#define TBCTL_CTRMODE_UP        0x0
+#define TBCTL_CTRMODE_DOWN      0x1
+#define TBCTL_CTRMODE_UPDOWN    0x2
+#define TBCTL_CTRMODE_FREEZE    0x3
+/* 
-----------------------------------------------------------------------------------------------
 */
+/* PWMSS Timebase clock check
+ *     check the timenase clock enable or not
+ *
+ *     @param PWMSS_ID :  PWM sumsystem ID (BBBIO_PWMSS0 ,BBBIO_PWMSS1, 
BBBIO_PWMSS2)
+ *
+ *     @return : 0 for disable timebase clock , 1 for enable for timebase clock
+ */
+static int PWMSS_TB_clock_check(unsigned int PWMSS_ID)
+{
+       volatile unsigned int* reg;
+       unsigned int reg_value ;
+
+       /* Control module check */
+       reg =(void *)CM_ptr + BBBIO_PWMSS_CTRL;
+       reg_value = *reg ;
+
+       return (reg_value & (1 << PWMSS_ID)) ;
+}
+
+/* 
-----------------------------------------------------------------------------------------------
 */
+/* PWM subsystem system control
+ *     enable or disable module clock
+ *
+ *     @param PWMSS_ID :  PWM sumsystem ID (BBBIO_PWMSS0 ,BBBIO_PWMSS1, 
BBBIO_PWMSS2).
+ *     @param enable : 0 for disable , else for enable .
+ *
+ *     @return : 1 for success ,  0 for error
+ */
+static int PWMSS_module_ctrl(unsigned int PWMSS_ID, int enable)
+{
+       volatile unsigned int *reg = NULL;
+       unsigned int module_set[] = {BBBIO_PWMSS0, BBBIO_PWMSS1, BBBIO_PWMSS2};
+       unsigned int module_clk_set[] = {BBBIO_CM_PER_EPWMSS0_CLKCTRL, 
BBBIO_CM_PER_EPWMSS1_CLKCTRL, BBBIO_CM_PER_EPWMSS2_CLKCTRL};
+       int ret = 1;
+
+       reg = (void*)cm_per_addr + module_clk_set[PWMSS_ID];
+       if(enable) {
+               if(PWMSS_TB_clock_check(module_set[PWMSS_ID])) {
+                       /* Enable module clock */
+                       *reg = 0x2;     /* Module enable and fully functional */
+                       return ret;
+               }
+#ifdef BBBIO_LIB_DBG
+               else {
+                       printf("PWMSS_module_ctrl : PWMSS-%d timebase clock 
disable in Control Module\n", PWMSS_ID);
+               }
+#endif
+               ret = 0 ;
+       }
+       *reg = 0x3 << 16;       /* Module is disabled and cannot be accessed */
+       return ret;
+}
+
+/* 
-----------------------------------------------------------------------------------------------
 */
+/* PWM init
+ *     iolib_init will run this function automatically
+ *
+ *      @return         : 1 for success , 0 for failed
+ */
+
+int BBBIO_PWM_Init()
+{
+       int i = 0;
+
+       if (memh == 0) {
+#ifdef BBBIO_LIB_DBG
+               printf("BBBIO_PWM_Init: memory not mapped?\n");
+#endif
+               return 0;
+       }
+
+       /* Create Memory map */
+       for (i = 0 ; i < 3 ; i ++) {
+               pwmss_ptr[i] = mmap(0, PWMSS_MMAP_LEN, PROT_READ | PROT_WRITE, 
MAP_SHARED, memh, PWMSS_AddressOffset[i]);
+               if(pwmss_ptr[i] == MAP_FAILED) {
+#ifdef BBBIO_LIB_DBG
+                       printf("BBBIO_PWM_Init: PWMSS %d mmap failure!\n", i);
+#endif
+                       goto INIT_ERROR ;
+               }
+               ecap_ptr[i] = (void *)pwmss_ptr[i] + 0x100 ;
+               eqep_ptr[i] = (void *)pwmss_ptr[i] + 0x180 ;
+               epwm_ptr[i] = (void *)pwmss_ptr[i] + 0x200 ;
+
+               if(!PWMSS_module_ctrl(i, 1)) {
+#ifdef BBBIO_LIB_DBG
+                       printf("BBBIO_PWM_Init: PWMSS %d clock  failure!\n", i);
+#endif
+                       goto INIT_ERROR ;
+               }
+       }
+       return 1;
+
+INIT_ERROR :
+       BBBIO_PWM_Release();
+       return 0;
+}
+
+/* 
-----------------------------------------------------------------------------------------------
 */
+void BBBIO_PWM_Release()
+{
+       int i = 0;
+       for(i = 0 ; i < 3 ; i ++) {
+               if(pwmss_ptr[i] != NULL) {
+                       munmap((void *)pwmss_ptr[i], PWMSS_MMAP_LEN);
+                       pwmss_ptr[i] = NULL;
+                       ecap_ptr[i] = NULL;
+                       eqep_ptr[i] = NULL;
+                       epwm_ptr[i] = NULL;
+               }
+       }
+}
+
+/* 
-----------------------------------------------------------------------------------------------
 */
+/* PWMSS status (no effect now)
+ *     set pluse rgument of epwm module
+ *
+ *      @param PWMID    : EPWMSS number , 0~3
+ *
+ *      @return         : 1 for success , 0 for failed
+ */
+int BBBIO_PWMSS_Status(unsigned int PWMID)
+{
+       int param_error = 1;
+       volatile unsigned int* reg;
+       unsigned int reg_value ;
+
+       if (memh == 0)
+            param_error = 0;
+
+       if (PWMID > 2)          /* if input is not EPWMSS 0~ WPEMSS 2 */
+            param_error = 0;
+
+       if (param_error == 0) {
+#ifdef BBBIO_LIB_DBG
+               printf("BBBIO_PWM_Status: parameter error!\n");
+#endif
+               return 0;
+       }
+
+       reg =(void *)CM_ptr + BBBIO_PWMSS_CTRL;
+
+       reg_value = *reg >> PWMID & 0x01 ;
+       if(reg_value == 0) {
+               printf("PWMSS [%d] Timebase clock Disable , Control Module 
[pwmss_ctrl register]\n", PWMID);
+       }
+       else {
+               reg=(void *)pwmss_ptr[PWMID] + PWMSS_CLKSTATUS;
+               reg_value = *reg ;
+
+               printf("PWMSS [%d] :\tCLKSTOP_ACK %d , CLK_EN_ACK %d , 
CLKSTOP_ACK %d , CLK_EN_ACK %d , CLKSTOP_ACK %d , CLK_EN_ACK %d\n",
+                       PWMID ,
+                       reg_value >>9 & 0x1 ,
+                       reg_value >>8 & 0x1 ,
+                       reg_value >>5 & 0x1 ,
+                       reg_value >>4 & 0x1 ,
+                       reg_value >>1 & 0x1 ,
+                       reg_value >>0 & 0x1 );
+       }
+       return 1 ;
+}
+/* 
-----------------------------------------------------------------------------------------------
 */
+/* PWMSS setting
+ *     set pluse rgument of epwm module
+ *
+ *      @param PWMID    : EPWMSS number , 0~2
+ *      @param HZ      : pluse HZ
+ *      @param dutyA    : Duty Cycle in ePWM A
+ *      @param dutyB    : Duty Cycle in ePWM B
+ *
+ *      @return         : 1 for success , 0 for failed
+ *
+ *      @example        :  BBBIO_PWMSS_Setting(0 , 50.0f , 50.0f , 25.0f);     
// Generate 50HZ pwm in PWM0 ,
+ *                                                                             
// duty cycle is 50% for ePWM0A , 25% for ePWM0B
+ *
+ *     @Note :
+ *             find an number nearst 65535 for TBPRD , to improve duty 
precision,
+ *
+ *             Using big TBPRD can increase the range of CMPA and CMPB ,
+ *             and it means we can get better precision on duty cycle.
+ *
+ *             EX : 20.25% duty cycle
+ *                  on TBPRD = 62500 , CMPA = 12656.25 ( .25 rejection) , real 
duty : 20.2496% (12656 /62500)
+ *                  on TBPRD = 6250  , CMPA = 1265.625 ( .625 rejection), real 
duty : 20.24%   (1265 6250)
+ *                  on TBPRD = 500   , CMPA = 101.25   ( .25 rejection) , real 
duty : 20.2%    (101/500)
+ *
+ *             Divisor = CLKDIV * HSPCLKDIV
+ *                             1 TBPRD : 10 ns (default)
+ *                     65535 TBPRD : 655350 ns
+ *                     65535 TBPRD : 655350 * Divisor ns  = X TBPRD : Cyclens
+ *
+ *             accrooding to that , we must find a Divisor value , let X 
nearest 65535 .
+ *             so , Divisor must  Nearest Cyclens/655350
+*/
+
+int BBBIO_PWMSS_Setting(unsigned int PWMID , float HZ ,float dutyA ,float 
dutyB)
+{
+       int param_error = 1;
+       volatile unsigned short* reg16 ;
+        if (memh == 0)
+            param_error = 0;
+        if (PWMID > 2)              // if input is not EPWMSS 0~ WPEMSS 2
+            param_error = 0;
+       if (HZ < 0 )
+           param_error = 0;
+       if(dutyA < 0.0f || dutyA > 100.0f || dutyB < 0.0f || dutyB > 100.0f)
+           param_error = 0;
+
+        if (param_error == 0) {
+#ifdef BBBIO_LIB_DBG
+               printf("BBBIO_PWMSS_Setting: parameter error!\n");
+#endif
+               return 0;
+        }
+
+       dutyA /= 100.0f ;
+       dutyB /= 100.0f ;
+
+       /* compute neccessary TBPRD */
+       float Cyclens =0.0f ;
+       float Divisor =0;
+       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;
+
+       Cyclens = 1000000000.0f / HZ ; /* 10^9 / HZ , comput time per cycle 
(ns) */
+
+
+       Divisor =  (Cyclens / 655350.0f) ;      /* am335x provide (128*14) 
divider , and per TBPRD means 10 ns when divider /1 ,
+                                                * and max TBPRD is 65535 , so 
, the max cycle is 128*14* 65535 *10ns
+                                                */
+#ifdef BBBIO_LIB_DBG
+       printf("Cyclens %f , Divisor %f\n", Cyclens, Divisor);
+#endif
+
+       if(Divisor > (128 * 14)) {
+#ifdef BBBIO_LIB_DBG
+               printf("BBBIO_PWMSS_Setting : Can't generate %f HZ \n", HZ);
+#endif
+               return 0;
+       }
+       else {
+               /* using Exhaustive Attack metho */
+               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)) {
+                                       NearCLKDIV = i ;
+                                       NearHSPCLKDIV = j ;
+                               }
+                       }
+               }
+#ifdef BBBIO_LIB_DBG
+               printf("nearest CLKDIV %f , HSPCLKDIV %f\n" 
,CLKDIV_div[NearCLKDIV] ,HSPCLKDIV_div[NearHSPCLKDIV]);
+#endif
+               NearTBPRD = (Cyclens / (10.0 *CLKDIV_div[NearCLKDIV] 
*HSPCLKDIV_div[NearHSPCLKDIV])) ;
+
+#ifdef BBBIO_LIB_DBG
+               printf("nearest TBPRD %d, %f %f\n ",NearTBPRD,NearTBPRD * 
dutyA, NearTBPRD * dutyB);
+#endif
+
+               /* setting clock diver and freeze time base */
+               reg16=(void*)epwm_ptr[PWMID] +EPWM_TBCTL;
+               *reg16 = TBCTL_CTRMODE_FREEZE | (NearCLKDIV << 10) | 
(NearHSPCLKDIV << 7);
+
+               /*  setting duty A and duty B */
+               reg16=(void*)epwm_ptr[PWMID] +EPWM_CMPB;
+               *reg16 =(unsigned short)((float)NearTBPRD * dutyB);
+
+               reg16=(void*)epwm_ptr[PWMID] +EPWM_CMPA;
+               *reg16 =(unsigned short)((float)NearTBPRD * dutyA);
+
+               reg16=(void*)epwm_ptr[PWMID] +EPWM_TBPRD;
+               *reg16 =(unsigned short)NearTBPRD;
+
+               /* reset time base counter */
+               reg16 = (void *)epwm_ptr[PWMID] + EPWM_TBCNT;
+               *reg16 = 0;
+       }
+       return 1;
+}
+/* 
-----------------------------------------------------------------------------------------------
 */
+/* Enable/Disable ehrPWM module
+ *      @param PWMID    : PWMSS number , 0~2
+ *
+ *      @return         : void
+ *
+ *      @example        : BBBIO_PWMSS_Enable(0) ;// Enable PWMSS 0
+ */
+
+void BBBIO_ehrPWM_Enable(unsigned int PWMSS_ID)
+{
+       volatile unsigned short *reg16 ;
+
+       reg16=(void*)epwm_ptr[PWMSS_ID] +EPWM_AQCTLA;
+       *reg16 = 0x2 | ( 0x3 << 4) ;
+               
+       reg16=(void*)epwm_ptr[PWMSS_ID] +EPWM_AQCTLB;
+       *reg16 = 0x2 | ( 0x3 << 8) ;
+
+       reg16 = (void *)epwm_ptr[PWMSS_ID] + EPWM_TBCNT;
+       *reg16 = 0;
+
+        reg16=(void *)epwm_ptr[PWMSS_ID] + EPWM_TBCTL;
+       *reg16 &= ~0x3;
+}
+
+void BBBIO_ehrPWM_Disable(unsigned int PWMSS_ID)
+{
+       volatile unsigned short *reg16 ;
+        reg16=(void *)epwm_ptr[PWMSS_ID] + EPWM_TBCTL;
+        *reg16 |= 0x3;
+
+       reg16=(void*)epwm_ptr[PWMSS_ID] +EPWM_AQCTLA;
+       *reg16 = 0x1 | ( 0x3 << 4) ;
+               
+       reg16=(void*)epwm_ptr[PWMSS_ID] +EPWM_AQCTLB;
+       *reg16 = 0x1 | ( 0x3 << 8) ;
+
+       reg16 = (void *)epwm_ptr[PWMSS_ID] + EPWM_TBCNT;
+       *reg16 = 0;
+}
+//--------------------------------------------------------
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/c/src/lib/libcpu/arm/shared/include/am335x.h 
b/c/src/lib/libcpu/arm/shared/include/am335x.h
index 2009cef..2ba5a98 100644
--- a/c/src/lib/libcpu/arm/shared/include/am335x.h
+++ b/c/src/lib/libcpu/arm/shared/include/am335x.h
@@ -467,4 +467,13 @@
 #define AM335X_CONF_EXT_WAKEUP 0xA00
 #define AM335X_CONF_RTC_KALDO_ENN 0xA04
 #define AM335X_CONF_USB0_DRVVBUS 0xA1C
-#define AM335X_CONF_USB1_DRVVBUS 0xA34
\ No newline at end of file
+#define AM335X_CONF_USB1_DRVVBUS 0xA34
+
+/* Registers for PWM Subsystem */
+#define BBBIO_PWMSS_CTRL               (0x664)
+#define BBBIO_CM_PER_EPWMSS0_CLKCTRL    (0xD4)
+#define BBBIO_CM_PER_EPWMSS1_CLKCTRL    (0xCC)
+#define BBBIO_CM_PER_EPWMSS2_CLKCTRL    (0xD8)
+#define BBBIO_CONTROL_MODULE           (0x44e10000)
+#define BBBIO_CM_PER_ADDR              (0x44e00000)
+#define PWMSS_CLKSTATUS                        (0xC)
-- 
2.7.1

_______________________________________________
devel mailing list
devel@rtems.org
http://lists.rtems.org/mailman/listinfo/devel

Reply via email to