Here is some code from a Beagleboard (not Beaglebone) the register bases and pin configs will be different, but it should give you an idea of how to control a PWM using QNX. It is *not* a driver in the QNX sense, but a low-level approach.
#include <stdlib.h> #include <stdio.h> #include <stdint.h> #include <signal.h> #include <unistd.h> #include <sys/mman.h> #include <sys/time.h> #include <time.h> #include <hw/inout.h> #define PG_SZ 0x1000 #define PAD_CONF_BASE 0x48002000 #define PAD_CTRL_G130_131 0x158 /* 131U 130L */ #define PAD_CTRL_G132_133 0x15c /* 133U 132L */ #define PAD_CTRL_G134_135 0x160 /* 135U 134L */ #define PAD_CTRL_G136_137 0x164 /* 137U 136L */ #define PAD_CTRL_G138_139 0x168 /* 139U 138L */ #define PWM_PAD_9 0x174 /* lwr */ #define PWM_PAD_10 0x174 /* upr */ #define PWM_PAD_11 0x178 /* lwr */ #define PAD_MODE1 1 #define PAD_MODE2 2 #define PAD_MODE4 4 #define PAD_PU_EN (1<<3) #define PAD_PU_UP 16 #define PAD_INPUTENABLE (1<<8) #define GPIO5_BASE 0x49056000 #define GPIO_DATAIN 0x038 #define GPIO_OE 0x034 #define GPIO_CLEARDATAOUT 0x90 #define GPIO_SETDATAOUT 0x94 #define PER_CLK_BASE 0x48005000 #define GPIO_CLK_EN_GPIO5 (1<<16) #define ICLK_OFFSET 0x10 #define EN_GPT9 (1<<10) #define GPT9_CLKSEL_OFFSET 0x40 #define CLKSEL_GPT9 (1<<7) #define CM_CLK_BASE 0x48004000 #define FCLK_ENABLE_OFFSET 0xA00 #define ICLK_ENABLE_OFFSET 0xA10 #define GPT10_CLKSEL_OFFSET 0xa40 #define EN_GPT10 (1<<11) #define CLKSEL_GPT10 (1<<6) #define EN_GPT11 (1<<12) #define CLKSEL_GPT11 (1<<7) #define TIMER_9_BASE 0x49040000 #define TIMER_10_BASE 0x48086000 #define TIMER_11_BASE 0x48088000 #define TIMER_TCLR 0x24 #define TIMER_START 1 #define TIMER_AUTORELOAD 2 #define TIMER_CE (1<<6) #define TIMER_SCPWM (1<<7) #define TIMER_PT (1<<12) #define TIMER_TRG (2<<10) #define TIMER_TCCR 0x28 #define TIMER_TLDR 0x2c #define TIMER_TMAR 0x38 #define SERVO_TLDR 0xfffc0857UL #define SYS_CLK 13000000UL #define SERVO_STOP 0xfffc5483UL #define SERVO_FWD (SERVO_TLDR + SYS_CLK*0.0018) #define SERVO_REV (SERVO_TLDR + SYS_CLK*0.0008) #define LEFT_SERVO_TRIM -488 #define LEFT_MOTOR 0 #define RIGHT_MOTOR 1 #define DUMP_MOTOR 2 #define MOTOR_REV -1 #define MOTOR_STOP 0 #define MOTOR_FWD 1 /* GPIO's are all mode 4 PIN Function PAD_CONF 4 GPT9_PWMEVT (left servo PWM) 0x48002174 L 10 GPT10_PWMEVT (right servo PWM) 0x48002174 U 6 GPT11_PWMEVT (dump servo PWM) 0x48002178 L 21 GPIO_130 (bucket sensor 1) 0x48002158 L 19 GPIO_131 (bucket sensor 2) 0x48002158 U 17 GPIO_132 (sensor 0) 0x4800215C L 15 GPIO_133 (sensor 1) 0x4800215C U 13 GPIO_134 (sensor 2) 0x48002160 L 11 GPIO_135 (start switch) 0x48002160 U 9 GPIO_136 (program switch 1) 0x48002164 L 7 GPIO_137 (program switch 2) 0x48002164 U 5 GPIO_138 (boot LED) 0x48002168 L */ /* GPIO5 starts at 128 */ #define BUCKET_SENSOR_1 2 #define BUCKET_SENSOR_2 3 #define SENSOR_GPIO(x) (x+4) #define START_SWITCH 7 #define PROGRAM_SWITCH_1 8 #define PROGRAM_SWITCH_2 9 static uintptr_t gpio_ptr; static uintptr_t left_servo_pwm; static uintptr_t right_servo_pwm; static uintptr_t dump_servo_pwm; void init() { uintptr_t padconf_ptr, clk_ptr; uint32_t tmp32; // turn on clks to GPIO5 and PWM9 clk_ptr = mmap_device_io(PG_SZ, PER_CLK_BASE); tmp32 = in32(clk_ptr); out32(clk_ptr, tmp32 | GPIO_CLK_EN_GPIO5 | EN_GPT9); // fclk tmp32 = in32(clk_ptr + ICLK_OFFSET); out32(clk_ptr + ICLK_OFFSET, tmp32 | GPIO_CLK_EN_GPIO5 | EN_GPT9); // iclk tmp32 = in32(clk_ptr + GPT9_CLKSEL_OFFSET); tmp32 |= CLKSEL_GPT9; out32(clk_ptr + GPT9_CLKSEL_OFFSET, tmp32); munmap_device_io(clk_ptr, PG_SZ); // turn on clks to PWM10 and PWM11 clk_ptr = mmap_device_io(PG_SZ, CM_CLK_BASE); tmp32 = in32(clk_ptr + FCLK_ENABLE_OFFSET); tmp32 |= EN_GPT10 | EN_GPT11; out32(clk_ptr + FCLK_ENABLE_OFFSET, tmp32); tmp32 = in32(clk_ptr + ICLK_ENABLE_OFFSET); tmp32 |= EN_GPT10 | EN_GPT11; out32(clk_ptr + ICLK_ENABLE_OFFSET, tmp32); tmp32 = in32(clk_ptr + GPT10_CLKSEL_OFFSET); tmp32 |= CLKSEL_GPT10 | CLKSEL_GPT11; out32(clk_ptr + GPT10_CLKSEL_OFFSET, tmp32); // select 13 MHz clock munmap_device_io(clk_ptr, PG_SZ); // program the input GPIO pins padconf_ptr = mmap_device_io(PG_SZ, PAD_CONF_BASE); tmp32 = PAD_MODE4 | (PAD_MODE4<<16) | PAD_INPUTENABLE | (PAD_INPUTENABLE<<16) | PAD_PU_EN | (PAD_PU_EN<<16); // for switch inputs out32(padconf_ptr + PAD_CTRL_G130_131, tmp32); out32(padconf_ptr + PAD_CTRL_G136_137, tmp32); tmp32 = PAD_MODE4 | (PAD_MODE4<<16) | PAD_INPUTENABLE | (PAD_INPUTENABLE<<16); // for photo sensor inputs out32(padconf_ptr + PAD_CTRL_G132_133, tmp32); tmp32 = PAD_MODE4 | (PAD_MODE4<<16) | PAD_INPUTENABLE | (PAD_INPUTENABLE<<16) | (PAD_PU_EN<<16); // for photo sensor input and run switch input out32(padconf_ptr + PAD_CTRL_G134_135, tmp32); // output BOOT LED tmp32 = in32(padconf_ptr + PAD_CTRL_G138_139); tmp32 &= 0xffff0000; tmp32 |= PAD_MODE4; out32(padconf_ptr + PAD_CTRL_G138_139, tmp32); // PWM pins tmp32 = PAD_MODE2 | (PAD_MODE2 << 16); out32(padconf_ptr + PWM_PAD_9, tmp32); tmp32 = in32(padconf_ptr + PWM_PAD_11); tmp32 &= 0xffff0000; tmp32 |= PAD_MODE2; out32(padconf_ptr + PWM_PAD_11, tmp32); munmap_device_io(padconf_ptr, PG_SZ); gpio_ptr = mmap_device_io(PG_SZ, GPIO5_BASE); // set sensor GPIOs as inputs tmp32 = in32(gpio_ptr + GPIO_OE); tmp32 |= (1<<BUCKET_SENSOR_1) | (1<<BUCKET_SENSOR_2) | (1<<SENSOR_GPIO(0)) | (1<<SENSOR_GPIO(1)) | (1<<SENSOR_GPIO(2)) | (1<<START_SWITCH) | (1<<PROGRAM_SWITCH_1) | (1<<PROGRAM_SWITCH_2); out32(gpio_ptr + GPIO_OE, tmp32); // map pwm's left_servo_pwm = mmap_device_io(PG_SZ, TIMER_9_BASE); right_servo_pwm = mmap_device_io(PG_SZ, TIMER_10_BASE); dump_servo_pwm = mmap_device_io(PG_SZ, TIMER_11_BASE); // setup/turn off all motors out32(left_servo_pwm + TIMER_TCLR, 0); // disable out32(left_servo_pwm + TIMER_TLDR, SERVO_TLDR); out32(left_servo_pwm + TIMER_TMAR, SERVO_STOP + LEFT_SERVO_TRIM); out32(left_servo_pwm + TIMER_TCCR, SERVO_TLDR); tmp32 = TIMER_START | TIMER_AUTORELOAD | TIMER_PT | TIMER_TRG | TIMER_CE | TIMER_SCPWM; out32(left_servo_pwm + TIMER_TCLR, tmp32); out32(right_servo_pwm + TIMER_TCLR, 0); // disable out32(right_servo_pwm + TIMER_TLDR, SERVO_TLDR); out32(right_servo_pwm + TIMER_TMAR, SERVO_STOP); out32(right_servo_pwm + TIMER_TCCR, SERVO_TLDR); tmp32 = TIMER_START | TIMER_AUTORELOAD | TIMER_PT | TIMER_TRG | TIMER_CE | TIMER_SCPWM; out32(right_servo_pwm + TIMER_TCLR, tmp32); out32(dump_servo_pwm + TIMER_TCLR, 0); // disable out32(dump_servo_pwm + TIMER_TLDR, SERVO_TLDR); out32(dump_servo_pwm + TIMER_TMAR, SERVO_STOP); out32(dump_servo_pwm + TIMER_TCCR, SERVO_TLDR); tmp32 = TIMER_START | TIMER_AUTORELOAD | TIMER_PT | TIMER_TRG | TIMER_CE | TIMER_SCPWM; out32(dump_servo_pwm + TIMER_TCLR, tmp32); // turn on BOOT LED } void dinit() { munmap_device_io(gpio_ptr, PG_SZ); munmap_device_io(left_servo_pwm, PG_SZ); munmap_device_io(right_servo_pwm, PG_SZ); munmap_device_io(dump_servo_pwm, PG_SZ); } void set_motor(int motor_num, int dir) // dir: -1 = back, 0 = stop, 1 = fwd { switch(motor_num) { case LEFT_MOTOR: switch(dir) { case MOTOR_FWD: out32(left_servo_pwm + TIMER_TMAR, SERVO_FWD); break; case MOTOR_STOP: out32(left_servo_pwm + TIMER_TMAR, SERVO_STOP + LEFT_SERVO_TRIM); break; case MOTOR_REV: out32(left_servo_pwm + TIMER_TMAR, SERVO_REV); break; } break; case RIGHT_MOTOR: switch(dir) { case MOTOR_FWD: out32(right_servo_pwm + TIMER_TMAR, SERVO_FWD); break; case MOTOR_STOP: out32(right_servo_pwm + TIMER_TMAR, SERVO_STOP); break; case MOTOR_REV: out32(right_servo_pwm + TIMER_TMAR, SERVO_REV); break; } break; case DUMP_MOTOR: switch(dir) { case MOTOR_FWD: out32(dump_servo_pwm + TIMER_TMAR, SERVO_FWD); break; case MOTOR_STOP: out32(dump_servo_pwm + TIMER_TMAR, SERVO_STOP); break; case MOTOR_REV: out32(dump_servo_pwm + TIMER_TMAR, SERVO_REV); break; } break; } } /* This returns sensor indication in bit positions as follows: * bit 0 bucket sensor 1 G130 * bit 1 bucket sensor 2 G131 * bit 2 photo sensor 1 G132 * bit 3 photo sensor 2 G133 * bit 4 photo sensor 3 G134 * bit 5 run switch G G135 * bit 6 program switch 1 G136 * bit 7 program switch 2 G137 */ int read_sensors() { uint32_t gpio, ret; gpio = in32(gpio_ptr + GPIO_DATAIN); ret = (gpio >> 2) & 0xff; return ret; } void run() { int sensors, i; int tmar; /* for (tmar = 0; tmar < 1000; tmar++) { out32(left_servo_pwm + TIMER_TMAR, SERVO_STOP - tmar); printf("tmar %d\n", tmar); usleep(10000); } for (tmar = 0; tmar < 1000; tmar++) { out32(left_servo_pwm + TIMER_TMAR, SERVO_STOP + tmar); printf("tmar %d\n", tmar); usleep(10000); } */ do { sensors = read_sensors(); usleep(1000); } while ( (sensors & (1<<5)) == 0); // wait until start button is pressed /* for (i = 1700; i <= 2000; i++) { int level; level = SERVO_TLDR + SYS_CLK * ( ( (float) i) / 1000000.0 ); printf("level: %d\n", level); out32(left_servo_pwm + TIMER_TMAR, level ); usleep(10000); } */ set_motor(LEFT_MOTOR, MOTOR_FWD); set_motor(RIGHT_MOTOR, MOTOR_FWD); set_motor(DUMP_MOTOR, MOTOR_FWD); sleep(5); set_motor(LEFT_MOTOR, MOTOR_REV); set_motor(RIGHT_MOTOR, MOTOR_REV); set_motor(DUMP_MOTOR, MOTOR_REV); sleep(5); set_motor(LEFT_MOTOR, MOTOR_STOP); set_motor(RIGHT_MOTOR, MOTOR_STOP); set_motor(DUMP_MOTOR, MOTOR_STOP); sensors = read_sensors(); printf("sensors: 0x%x\n", sensors); } int main(int argc, char *argv[]) { init(); run(); dinit(); return EXIT_SUCCESS; } On Tuesday, May 19, 2015 at 8:52:12 PM UTC-6, liyaoshi wrote: > > Sorry , missing the key driver of pwm . > As I remember , QNX dont have the pwm as a architecture driver . > > maybe from other bsp source as a reference ? > > 2015-05-20 10:48 GMT+08:00 liyaoshi <liya...@gmail.com <javascript:>>: > >> >> http://community.qnx.com/sf/wiki/do/viewPage/projects.bsp/wiki/TiAm335Beaglebone >> >> 2015-05-18 10:31 GMT+08:00 Charles Steinkuehler <cha...@steinkuehler.net >> <javascript:>>: >> >>> On 5/17/2015 8:03 AM, amir...@gmail.com <javascript:> wrote: >>> > I would like to have a PWM output signal from BeagleBone Black. I have >>> to >>> > use QNX operating System (due to Real-Time Constraints) on my >>> BeagleBone. >>> > Do you have any suggestions how to do that? >>> > There is no out of the box QNX bsp to do that. >>> >>> If you want to use QNX, you'll have to perform all the hardware setup >>> and configuration yourself. It's reasonably straight-forward to >>> interface to the PWM registers (see the TRM for details), but you'll >>> also need to setup the clock multiplexing and resets before anything >>> will work at all. The Linux kernel code is a great reference for >>> getting the clocks/resets configured properly, or you can refer to the >>> TI bare-metal example applications. >>> >>> ...or see if the QNX folks will make a proper AM335x BSP for you. :) >>> >>> -- >>> Charles Steinkuehler >>> cha...@steinkuehler.net <javascript:> >>> >>> -- >>> 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...@googlegroups.com <javascript:>. >>> 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.