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.

Reply via email to