I think PWM is an array of integers. If I give pwm+offset, then it will be
equivalent to pwm + 4 * offset. Thats why I gave pwm+offset/4 for the
correct index of array. Isn't that correct.


On Sun, Apr 6, 2014 at 12:01 PM, Przemek Klosowski <
[email protected]> wrote:

> Is it possible that your pwm is an array of ints, and you're indexing
> it by byte offsets?
> I think pwm[OFFSET] is referring to pwm+4*OFFSET, whereas you need
> pwm+OFFSET
>
> On Sun, Apr 6, 2014 at 1:50 AM, milkyway <[email protected]>
> wrote:
> > I am using GPTIMER_PWM_9 to generate a square wave. Following is my code
> >
> > #include <stdio.h>
> > #include <stdlib.h>
> > #include <sys/types.h>
> > #include <sys/stat.h>
> > #include <unistd.h>
> > #include <fcntl.h>
> > #include <sys/mman.h>
> >
> > #define MEMORY_BASE_ADDRESS                     0x48000000
> > #define GPTIMER9_BASE_ADDRESS                   0x49040000
> > #define GPTIMER9_PADCONF_REGISTER               0x2174/4
> > #define GPTIMER9_RELOAD_REGISTER                0x002c/4
> > #define GPTIMER9_COMAPARATOR_REGISTER   0x0038/4
> > #define GPTIMER9_CONTROL_REGISTER               0x0024/4
> > #define GPTIMER9_COUNTER_REGISTER               0x0028/4
> >
> >
> > int main(void)
> > {
> >
> >         int config_fd, j, pwm_fd;
> >         volatile unsigned int *config, *pwm;;
> >     config_fd = open("/dev/mem", O_RDWR | O_SYNC);
> >     printf ("Open file descriptor for PADCONFIG\n");
> >         if (config_fd < 0)
> >         {
> >       printf("Could not open PADCONFIG memory fd\n");
> >       return 0;
> >     }
> >
> >     // Pad configuration
> >     printf ("Setting PAD configuration register\n");
> >     config = (unsigned int*) mmap(NULL, 0x10000, PROT_READ | PROT_WRITE,
> > MAP_SHARED, config_fd, MEMORY_BASE_ADDRESS);
> >     if (config == MAP_FAILED)
> >         {
> >       printf("Pinconfig Mapping failed\n");
> >       close(config_fd);
> >       return 1;
> >     }
> >
> >     printf ("Setting padconf register for PWM\n");
> >     config[GPTIMER9_PADCONF_REGISTER] =
> config[GPTIMER9_PADCONF_REGISTER] &
> > 0xffff0000 | 0x00000002; // setting 0x48002714 as gpt9_pwm_evt
> >         printf("The pin has been succesfully selected as
> gpt9_pwm_evt\n");
> >         close(config_fd);
> >     printf ("Opening file descriptor for PWM\n");
> >     pwm_fd = open("/dev/mem", O_RDWR | O_SYNC);
> >     if (pwm_fd < 0)
> >         {
> >       printf("Could not open GPIO memory fd\n");
> >       return 2;
> >     }
> >         printf ("Memory opened for pwm settings\n");
> >     pwm = (unsigned int*) mmap(NULL, 0x1000, PROT_READ | PROT_WRITE,
> > MAP_SHARED, pwm_fd, GPTIMER9_BASE_ADDRESS);
> >     if (pwm == MAP_FAILED)
> >         {
> >       printf ("PWM Mapping failed\n");
> >       close(pwm_fd);
> >       return 3;
> >     }
> >     printf ("Setting up PWM\n");
> >         pwm[GPTIMER9_CONTROL_REGISTER] = 0;
> >         pwm[GPTIMER9_RELOAD_REGISTER] = 0x0000ff; // initial value of pwm
> > during overflow
> >         pwm[GPTIMER9_COUNTER_REGISTER] = 0x0000ff; // initial value of
> pwm
> > during overflow
> >         pwm[GPTIMER9_COMAPARATOR_REGISTER] = 0x0fffff; // overflow value
> >         pwm[GPTIMER9_CONTROL_REGISTER] = 0x18c3;  //timer control
> register
> >     printf ("PWM Started\n");
> >         close(pwm_fd);
> >         return 0;
> > }
> >
> >
> > But I am getting an error as follows
> >
> > root@localhost:/home/dell/sample_programs# ./a.out
> > open file descriptor for PADCONFIG
> > map PINCONFIG
> > Setting padconf register for PWM
> > The pin has been succesfully selected as gpt9_pwm_evt
> > opening file descriptor for PWM
> > Memory opened for pwm settings
> > setting up pwm
> > Bus error
> >
> > Can anybody help me to fix this issue?
> >
> > On Sunday, 13 February 2011 22:11:36 UTC+5:30, mohit hada wrote:
> >>
> >> Hi to all
> >>
> >> Thanks a lot Ben for your help in your last mail....
> >>
> >> Now I have been able to generate PWM but on beagle board xM, I have been
> >> able to generate maximum 4.34 MHz... The code modified is given
> >> below, my added parts are indicated separately. But Now My doubt is why
> I
> >> get so low value of 4.34 MHz with 26MHz system clock. Is it that I am
> not
> >> able to use 26 MHz or ??? Please help. Thanks....
> >>
> >> omap3530-pwm-demo.c :
> >>
> >> #include <glib.h>
> >> #include <unistd.h>
> >> #include <stdio.h>
> >> #include <errno.h>
> >>
> >>
> >> #include <stdlib.h>
> >> #include <sys/types.h>
> >> #include <sys/stat.h>
> >> #include <fcntl.h>
> >> #include <sys/mman.h>
> >>
> >>
> >>
> >> #include "omap3530-pwm.h"
> >>
> >> int
> >> main(int argc, char **argv)
> >> {
> >> int mem_fd;
> >> int i;
> >>
> >>
> >>
> >>  /* New addition written by mohit */
> >> volatile ulong *pinconf, *clk_selec;
> >>
> >>   mem_fd = open("/dev/mem", O_RDWR | O_SYNC);
> >>   pinconf = (ulong*)mmap(NULL, 0x10000, PROT_READ | PROT_WRITE,
> >> MAP_SHARED, mem_fd, 0x48000000);
> >>   if (pinconf == MAP_FAILED) {
> >>     printf("Pinconf Mapping failed\n");
> >>     close(mem_fd);
> >>     return 0;
> >>   }
> >>
> >>  pinconf[0x2174/4] = 0x011A011A; //PIN CONFIGURED AS BIDIRECTIONAL
> >>  pinconf[0x2178/4] = 0x011A011A; //PIN CONFIGURED AS BIDIRECTIONAL
> >>  close(mem_fd);
> >>
> >>
> >>    mem_fd = pwm_open_devmem();
> >>
> >>     if (mem_fd == -1) {
> >> //        g_error("Unable to open /dev/mem, are you root?: %s",
> >> g_strerror(errno));
> >>     }
> >>
> >>    pwm_clkfreq_sel(mem_fd, TRUE, TRUE);
> >>    pwm_close_devmem(mem_fd);
> >>
> >>
> >> /*program end by mohit*/
> >>
> >>
> >>     mem_fd = pwm_open_devmem();
> >>
> >>     if (mem_fd == -1) {
> >> //        g_error("Unable to open /dev/mem, are you root?: %s",
> >> g_strerror(errno));
> >>     }
> >>
> >>
> >> ////////////////////////////////INCLUSION OF ADDITIONAL FUNCTION CALLS
> FOR
> >> FCLK AND ICLK
> ENABLE///////////////////////////////////////////////////////
> >>
> >>     // ENABLE ICLK CLOCK
> >>     pwm_iclken_clock(mem_fd, TRUE, TRUE);
> >>     pwm_close_devmem(mem_fd);
> >>
> >>     mem_fd = pwm_open_devmem();
> >>
> >>     if (mem_fd == -1) {
> >> //        g_error("Unable to open /dev/mem, are you root?: %s",
> >> g_strerror(errno));
> >>     }
> >>
> >>     // ENABLE FCLK CLOCK
> >>     pwm_fclken_clock(mem_fd, TRUE, TRUE);
> >>     pwm_close_devmem(mem_fd);
> >>
> >>     mem_fd = pwm_open_devmem();
> >>
> >>     if (mem_fd == -1) {
> >> //        g_error("Unable to open /dev/mem, are you root?: %s",
> >> g_strerror(errno));
> >>     }
> >>
> >>
> >>
> ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
> >>
> >>
> >>     // Set instances 10 and 11 to use the 13 Mhz clock
> >>     pwm_config_clock(mem_fd, TRUE, TRUE);
> >>     guint8 *gpt10 = pwm_mmap_instance(mem_fd, 10);
> >>     guint8 *gpt11 = pwm_mmap_instance(mem_fd, 11);
> >>
> >>     // Get the resolution for 20 kHz PWM
> >>     guint32 resolution = pwm_calc_resolution(20000000,
> >> PWM_FREQUENCY_13MHZ);
> >>
> >>
> >>     // Ramp up and down a bit
> >>     for(i = 0; i <= 100; i++) {
> >> //        g_print("%3d\n", i);
> >>         pwm_config_timer(gpt10, resolution, i / 100.0);
> >>         pwm_config_timer(gpt11, resolution, i / 100.0);
> >>         usleep(100000);
> >>     }
> >>     sleep(500);
> >>     for (i = 100; i >= 0; i--) {
> >>  //       g_print("%3d\n", i);
> >>         pwm_config_timer(gpt10, resolution, i / 100.0);
> >>         pwm_config_timer(gpt11, resolution, i / 100.0);
> >>         usleep(100000);
> >>     }
> >>
> >>     pwm_munmap_instance(gpt10);
> >>     pwm_munmap_instance(gpt11);
> >>     pwm_close_devmem(mem_fd);
> >> }
> >>
> >> // vim: set ts=4 et :
> >>
> >>
> >> omap3530-pwm.c :
> >>
> >> #include <glib.h>
> >> #include <unistd.h>
> >> #include <stdio.h>
> >> #include <fcntl.h>
> >> #include <sys/types.h>
> >> #include <sys/stat.h>
> >> #include <sys/mman.h>
> >> #include <errno.h>
> >>
> >> #include "omap3530-pwm.h"
> >>
> >> // Clock configuration registers (TRM p. 470)
> >> #define CM_CLKSEL_CORE 0x48004A40
> >> #define CLKSEL_GPT10_MASK (1 << 6)
> >> #define CLKSEL_GPT11_MASK (1 << 7)
> >>
> >>
> >>
> >>
> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
> >>
> >>
> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
> >>
> >> #define CM_CLKSEL_FCLK 0x48004A00
> >> #define FCLKSEL_GPT10_MASK (1 << 11)
> >> #define FCLKSEL_GPT11_MASK (1 << 12)
> >>
> >> #define CM_CLKSEL_ICLK 0x48004A10
> >> #define ICLKSEL_GPT10_MASK (1 << 11)
> >> #define ICLKSEL_GPT11_MASK (1 << 12)
> >>
> >> #define CLKFREQ_SEL 0x48306D40
> >> #define BIT1 (1 << 1)
> >> #define BIT0 (1 << 0)
> >>
> >>
> >>
> >>
> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
> >>
> >>
> //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
> >>
> >> // GPTIMER register offsets
> >> #define GPT_REG_TCLR 0x024
> >> #define GPT_REG_TCRR 0x028
> >> #define GPT_REG_TLDR 0x02c
> >> #define GPT_REG_TMAR 0x038
> >>
> >> // Get a guint32 pointer to the register in block `instance` at byte
> >> // offset `offset`.
> >> #define REG32_PTR(instance, offset) ((volatile guint32*) (instance +
> >> offset))
> >>
> >>
> >> // General purpose timer instances.  Not all of these can actually be
> >> // used for PWM --- see the TRM for more information.
> >> static guint32 gpt_instance_addrs[] = {
> >>     0x4903e000, // GPTIMER8
> >>     0x49040000, // GPTIMER9
> >>     0x48086000, // GPTIMER10
> >>     0x48088000, // GPTIMER11
> >> };
> >>
> >>
> >> // The default Linux page size is 4k and the GP timer register
> >> // blocks are aligned to 4k.  Therefore it is convenient to just
> >> // assume that pages are aligned there for the purposes of mmap()
> >> // (since mmap only maps aligned pages).  This function checks
> >> // that assumption and aborts if it is untrue.
> >> static void
> >> check_pagesize(void)
> >> {
> >>     if (getpagesize() != 4096) {
> >> //        g_error("The page size is %d.  Must be 4096.", getpagesize());
> >>     }
> >> }
> >>
> >> // Simply a wrapper around mmap that passes the correct arguments
> >> // for mapping a register block.  `instance_number` must be between
> >> // 1 and 12, or errno will be set to EDOM and MAP_FAILED returned.
> >> // Otherwise the return value is that of `mmap()`.
> >> guint8*
> >> pwm_mmap_instance(int mem_fd, int instance_number)
> >> {
> >>     if (instance_number < 8 || instance_number > 11) {
> >>         errno = EDOM;
> >>         return MAP_FAILED;
> >>     }
> >>     int instance_addr = gpt_instance_addrs[instance_number - 8];
> >>     return mmap(NULL, 4096, PROT_READ | PROT_WRITE, MAP_SHARED, mem_fd,
> >> instance_addr);
> >> }
> >>
> >> // The inverse of `pwm_mmap_instance()`, this is simply a wrapper
> >> // arount `munmap()`.  It returns the underlying `munmap()` call's
> >> // return value.
> >> int
> >> pwm_munmap_instance(guint8 *instance)
> >> {
> >>     return munmap(instance, 4096);
> >> }
> >>
> >> // Configure the clocks for GPTIMER10 and GPTIMER11, which can be set to
> >> // use the 13 MHz system clock (otherwise they use the 32 kHz clock like
> >> // the rest of the timers).  Return -1 on failure, with errno set.
> >> int
> >> pwm_config_clock(int mem_fd, gboolean gptimer10_13mhz, gboolean
> >> gptimer11_13mhz)
> >> {
> >>     int page_addr = CM_CLKSEL_CORE & 0xfffff000;
> >>     int offset = CM_CLKSEL_CORE & 0xfff;
> >>
> >>     guint8 *registers = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
> >> MAP_SHARED, mem_fd, page_addr);
> >>     if (registers == MAP_FAILED) {
> >>         return -1;
> >>     }
> >>
> >>     guint32 value = *REG32_PTR(registers, offset);
> >>     value &= ~(CLKSEL_GPT10_MASK | CLKSEL_GPT11_MASK);
> >>     if (gptimer10_13mhz) value |= CLKSEL_GPT10_MASK;
> >>     if (gptimer11_13mhz) value |= CLKSEL_GPT11_MASK;
> >>     *REG32_PTR(registers, offset) = value;
> >>
> >>     return munmap(registers, 4096);
> >> }
> >>
> >>
> >>
> ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
> >>
> >>
> ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
> >> int
> >> pwm_fclken_clock(int mem_fd, gboolean gptimer10_13mhz, gboolean
> >> gptimer11_13mhz)
> >> {
> >>     int page_addr = CM_CLKSEL_FCLK & 0xfffff000;
> >>     int offset = CM_CLKSEL_FCLK & 0xfff;
> >>
> >>     guint8 *registers = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
> >> MAP_SHARED, mem_fd, page_addr);
> >>     if (registers == MAP_FAILED) {
> >>         return -1;
> >>     }
> >>
> >>     guint32 value = *REG32_PTR(registers, offset);
> >>     value &= ~(FCLKSEL_GPT10_MASK | FCLKSEL_GPT11_MASK);
> >>     if (gptimer10_13mhz) value |= FCLKSEL_GPT10_MASK;
> >>     if (gptimer11_13mhz) value |= FCLKSEL_GPT11_MASK;
> >>     *REG32_PTR(registers, offset) = value;
> >>
> >>     return munmap(registers, 4096);
> >> }
> >>
> >>
> >> int
> >> pwm_iclken_clock(int mem_fd, gboolean gptimer10_13mhz, gboolean
> >> gptimer11_13mhz)
> >> {
> >>     int page_addr = CM_CLKSEL_ICLK & 0xfffff000;
> >>     int offset = CM_CLKSEL_ICLK & 0xfff;
> >>
> >>     guint8 *registers = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
> >> MAP_SHARED, mem_fd, page_addr);
> >>     if (registers == MAP_FAILED) {
> >>         return -1;
> >>     }
> >>
> >>     guint32 value = *REG32_PTR(registers, offset);
> >>     value &= ~(ICLKSEL_GPT10_MASK | ICLKSEL_GPT11_MASK);
> >>     if (gptimer10_13mhz) value |= ICLKSEL_GPT10_MASK;
> >>     if (gptimer11_13mhz) value |= ICLKSEL_GPT11_MASK;
> >>     *REG32_PTR(registers, offset) = value;
> >>
> >>     return munmap(registers, 4096);
> >> }
> >>
> >>
> >> int
> >> pwm_clkfreq_sel(int mem_fd, gboolean gptimer10_13mhz, gboolean
> >> gptimer11_13mhz)
> >> {
> >>     int page_addr = CLKFREQ_SEL & 0xfffff000;
> >>     int offset = CLKFREQ_SEL & 0xfff;
> >>
> >>     guint8 *registers = mmap(NULL, 4096, PROT_READ | PROT_WRITE,
> >> MAP_SHARED, mem_fd, page_addr);
> >>     if (registers == MAP_FAILED) {
> >>         return -1;
> >>     }
> >>
> >>     guint32 value = *REG32_PTR(registers, offset);
> >>     value &= ~(BIT1 | BIT0);
> >>     if (gptimer10_13mhz) value |= BIT1;
> >>     if (gptimer11_13mhz) value |= BIT0;
> >>     *REG32_PTR(registers, offset) = value;
> >>
> >>     return munmap(registers, 4096);
> >> }
> >>
> >>
> >>
> ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
> >>
> >>
> ///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
> >>
> >>
> >> // Calculate the resolution of the PWM (the number of clock ticks
> >> // in the period), which is passed to `pwm_config_timer()`.
> >> guint32
> >> pwm_calc_resolution(int pwm_frequency, int clock_frequency)
> >> {
> >>     float pwm_period = 1.0 / pwm_frequency;
> >>     float clock_period = 1.0 / clock_frequency;
> >>     return (guint32) (pwm_period / clock_period);
> >> }
> >>
> >> // Initialize the control registers of the specified timer
> >> // instance for PWM at the specified resolution.
> >> void
> >> pwm_config_timer(guint8 *instance, guint32 resolution, float duty_cycle)
> >> {
> >>     guint32 counter_start = 0xffffffff - resolution;
> >>     guint32 dc = 0xffffffff - ((guint32) (resolution * duty_cycle));
> >>
> >>     // Edge condition: the duty cycle is set within two units of the
> >> overflow
> >>     // value.  Loading the register with this value shouldn't be done
> (TRM
> >> 16.2.4.6).
> >>     if (0xffffffff - dc <= 2) {
> >>         dc = 0xffffffff - 2;
> >>     }
> >>
> >>     // Edge condition: TMAR will be set to within two units of the
> >> overflow
> >>     // value.  This means that the resolution is extremely low, which
> >> doesn't
> >>     // really make sense, but whatever.
> >>     if (0xffffffff - counter_start <= 2) {
> >>         counter_start = 0xffffffff - 2;
> >>     }
> >>
> >>     *REG32_PTR(instance, GPT_REG_TCLR) = 0; // Turn off
> >>     *REG32_PTR(instance, GPT_REG_TCRR) = counter_start;
> >>     *REG32_PTR(instance, GPT_REG_TLDR) = counter_start;
> >>     *REG32_PTR(instance, GPT_REG_TMAR) = dc;
> >>     *REG32_PTR(instance, GPT_REG_TCLR) = (
> >>         (1 << 0)  | // ST -- enable counter
> >>         (1 << 1)  | // AR -- autoreload on overflow
> >>         (1 << 6)  | // CE -- compare enabled
> >>         (1 << 7)  | // SCPWM -- invert pulse
> >>         (2 << 10) | // TRG -- overflow and match trigger
> >>         (1 << 12)   // PT -- toggle PWM mode
> >>     );
> >> }
> >>
> >> int
> >> pwm_open_devmem(void)
> >> {
> >>     check_pagesize();
> >>
> >>     return open("/dev/mem", O_RDWR | O_SYNC);
> >> }
> >>
> >> void
> >> pwm_close_devmem(int dev_fd)
> >> {
> >>     /* This function is useful! */
> >>     close(dev_fd);
> >> }
> >>
> >> // vim: set ts=4 expandtab :
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >>
> >> On Sun, Feb 13, 2011 at 6:46 PM, Ben Gamari <[email protected]>
> wrote:
> >>>
> >>> On Sun, 13 Feb 2011 14:14:02 +0530, mohit hada <[email protected]>
> wrote:
> >>> > I get the following error :
> >>> > *
> >>> > root@beagleboard:~#
> >>> > ./pwm-demo
> >>> >
> >>> > [  174.893035] Unhandled fault: external abort on non-linefetch
> >>> > (0x1818) at
> >>> > 0x4001e024
> >>> > Bus error  *
> >>> >
> >>> > Please tell me some remedy of this... running a simple gpio program
> did
> >>> > run
> >>> > on the BB-xM fine.
> >>> >
> >>> A little bit of Googling goes a long ways:
> >>>
> >>>  http://e2e.ti.com/support/embedded/f/354/p/49197/196854.aspx
> >>>  http://markmail.org/message/dzcyrbqkeeivesyq
> >>>
> >>>
> http://linux.omap.com/pipermail/linux-omap-open-source/2007-November/012094.html
> >>>
> >>> The problem is apparently that your pwm demo doesn't enable the PWM
> >>> unit's clocks before accessing the PWM. You should take a look at
> >>> section 16.2 to determine which clocks are needed.
> >>>
> >>> - Ben
> >>
> >>
> >>
> >>
> >> --
> >> Mohit Hada (owner)
> >> Technid Solutions(An Embedded and FPGA based Design and Development
> >> Company)
> >>
> >> Registered Office :
> >>
> >> Flat No- 7,
> >> 73, Ashutosh Mukherjee Road,
> >> Kolkata - 700025
> >>
> >> ph : 08820074382 (preferred) / 09322156564
> >>
> >>
> >> Ass No : 110720200429
> >>
> >> Vat No. - 19415754062
> >>
> >>
> >>
> > --
> > For more options, visit http://beagleboard.org/discuss
> > ---
> > You received this message because you are subscribed to the Google Groups
> > "BeagleBoard" group.
> > To unsubscribe from this group and stop receiving emails from it, send an
> > email to [email protected].
> > For more options, visit https://groups.google.com/d/optout.
>
> --
> For more options, visit http://beagleboard.org/discuss
> ---
> You received this message because you are subscribed to a topic in the
> Google Groups "BeagleBoard" group.
> To unsubscribe from this topic, visit
> https://groups.google.com/d/topic/beagleboard/7kLlxZ7fg80/unsubscribe.
> To unsubscribe from this group and all its topics, send an email to
> [email protected].
> For more options, visit https://groups.google.com/d/optout.
>

-- 
For more options, visit http://beagleboard.org/discuss
--- 
You received this message because you are subscribed to the Google Groups 
"BeagleBoard" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
For more options, visit https://groups.google.com/d/optout.

Reply via email to