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 <muhammednouf...@gmail.com> 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 <bgamar...@gmail.com> wrote:
>>>
>>> On Sun, 13 Feb 2011 14:14:02 +0530, mohit hada <mohi...@gmail.com> 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 beagleboard+unsubscr...@googlegroups.com.
> 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 beagleboard+unsubscr...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Reply via email to