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.