197 строки
6.3 KiB
C
197 строки
6.3 KiB
C
/*
|
|
* (c) 2017, SWD Embedded Systems Limited, http://www.kpda.ru
|
|
*/
|
|
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <errno.h>
|
|
#include <unistd.h>
|
|
#include <devctl.h>
|
|
#include <fcntl.h>
|
|
|
|
#include <devctl.h>
|
|
#include <inttypes.h>
|
|
|
|
#include <sys/iomsg.h>
|
|
#include <hw/gpio_am35.h>
|
|
|
|
|
|
typedef struct _gpio_ctrl {
|
|
char *devname; /* port prefix */
|
|
uint8_t pin; /* pin num or reg mask depending on mode */
|
|
uint16_t dir; /* pins direction ( 0 for input, 1 for output ) */
|
|
uint16_t outval; /* output pin state */
|
|
uint8_t chwait; /* wait for pin change pulse events */
|
|
uint8_t verbose;
|
|
} gpio_ctrl_t;
|
|
|
|
|
|
void parse_options( int argc, char *argv[], gpio_ctrl_t *gc )
|
|
{
|
|
int c;
|
|
unsigned gpio_pin;
|
|
|
|
while ( (c = getopt( argc, argv, "n:p:d:o:Wv" ) ) != -1 )
|
|
{
|
|
switch ( c )
|
|
{
|
|
case 'n':
|
|
gc->devname = optarg;
|
|
break;
|
|
|
|
case 'p':
|
|
gpio_pin = strtoul( optarg, NULL, 0 );
|
|
if ( (gpio_pin > 191) || (gpio_pin < 0) )
|
|
{
|
|
printf( "GPIO control: Error! Valid GPIO pin number is from range 0 ~ 191.\n" );
|
|
exit( -1 );
|
|
}
|
|
gc->pin = gpio_pin;
|
|
break;
|
|
|
|
case 'd':
|
|
gc->dir = strtoul( optarg, NULL, 0 );
|
|
if ( gc->dir != 0 )
|
|
gc->dir = GPIO_OUTPUT;
|
|
else
|
|
gc->dir = GPIO_INPUT;
|
|
break;
|
|
|
|
case 'o':
|
|
gc->outval = strtoul( optarg, NULL, 0 );
|
|
if ( gc->outval != 0 )
|
|
gc->outval = 1;
|
|
else
|
|
gc->outval = 0;
|
|
break;
|
|
|
|
case 'W':
|
|
gc->chwait = 1;
|
|
break;
|
|
|
|
case 'v':
|
|
gc->verbose++;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
int main( int argc, char *argv[] )
|
|
{
|
|
gpio_ctrl_t gpio_ctrl;
|
|
gpio_devctl_t msg;
|
|
int fd;
|
|
int status;
|
|
|
|
memset( &gpio_ctrl, 0 , sizeof( gpio_ctrl_t ) );
|
|
gpio_ctrl.devname = GPIO_DEVICE_NAME;
|
|
gpio_ctrl.dir = -1;
|
|
gpio_ctrl.outval = 0;
|
|
gpio_ctrl.verbose = 1;
|
|
gpio_ctrl.pin = 178;
|
|
|
|
parse_options( argc, argv, &gpio_ctrl );
|
|
|
|
fd = open( gpio_ctrl.devname, O_RDWR );
|
|
if ( fd == -1 )
|
|
{
|
|
printf( "GPIO control: Error! Failed to open %s: %s\n", gpio_ctrl.devname, strerror( errno ) );
|
|
return (-1);
|
|
}
|
|
|
|
if ( gpio_ctrl.dir == GPIO_INPUT )
|
|
{
|
|
printf( "GPIO control: Reading GPIO pin %d \n", gpio_ctrl.pin );
|
|
|
|
msg.set_input.pin_num = gpio_ctrl.pin;
|
|
|
|
// Set pin direction
|
|
if ( ( status = devctl( fd, DCMD_SET_INPUT, &msg, sizeof( msg ), NULL ) ) )
|
|
printf( "GPIO control: Error! GPIO DCMD_SET_INPUT devctl failed; status = %d\n", status );
|
|
else
|
|
printf( "GPIO control: Pin %d direction: INPUT\n", gpio_ctrl.pin );
|
|
|
|
if ( ( status = devctl( fd, DCMD_READ, &msg, sizeof( msg ), NULL ) ) )
|
|
{
|
|
printf( "GPIO control: Error! GPIO DCMD_READ devctl failed; status = %d\n", status );
|
|
return (-1);
|
|
} else {
|
|
printf( "GPIO control: Pin %d value: %d\n", msg.cmd_read.pin_num, msg.cmd_read.data );
|
|
return (msg.cmd_read.data);
|
|
}
|
|
} else
|
|
if ( gpio_ctrl.dir == GPIO_OUTPUT )
|
|
{
|
|
printf( "GPIO control: Setting GPIO pin %d value %d\n", gpio_ctrl.pin, gpio_ctrl.outval );
|
|
|
|
msg.set_output.pin_num = gpio_ctrl.pin;
|
|
|
|
// Set pin direction
|
|
if ( ( status = devctl( fd, DCMD_SET_OUTPUT, &msg, sizeof( msg ), NULL ) ) )
|
|
printf( "GPIO control: Error! GPIO DCMD_SET_OUTPUT devctl failed; status = %d\n", status );
|
|
else
|
|
printf( "GPIO control: Pin %d direction: OUTPUT\n", gpio_ctrl.pin );
|
|
|
|
msg.cmd_write.pin_num = gpio_ctrl.pin;
|
|
msg.cmd_write.data = gpio_ctrl.outval;
|
|
|
|
if ( ( status = devctl( fd, DCMD_WRITE, &msg, sizeof( msg ), NULL ) ) )
|
|
printf( "GPIO control: Error! GPIO DCMD_WRITE devctl failed; status = %d\n", status );
|
|
else
|
|
printf( "GPIO control: Pin %d value: %d\n", msg.cmd_write.pin_num, msg.cmd_write.data );
|
|
}
|
|
|
|
if ( gpio_ctrl.chwait )
|
|
{
|
|
int chid;
|
|
int coid;
|
|
struct _pulse pulse;
|
|
|
|
// we need a channel to receive the pulse notification on
|
|
chid = ChannelCreate( 0 );
|
|
|
|
// and we need a connection to that channel for the pulse to be delivered on
|
|
coid = ConnectAttach( 0, 0, chid, _NTO_SIDE_CHANNEL, 0 );
|
|
|
|
msg.cmd_intterupt.pin_num = gpio_ctrl.pin;
|
|
msg.cmd_intterupt.level = GPIO_INT_LEVEL_LOW;
|
|
msg.cmd_intterupt.coid = coid;
|
|
|
|
// Set pin direction
|
|
if ( ( status = devctl( fd, DCMD_SET_INPUT, &msg, sizeof( msg ), NULL ) ) )
|
|
printf( "GPIO control: Error! GPIO DCMD_SET_INPUT devctl failed; status = %d\n", status );
|
|
else
|
|
printf( "GPIO control: Pin %d direction: INPUT\n", gpio_ctrl.pin );
|
|
|
|
printf( "GPIO control: Client: enable interrupts from GPIO pin %d \n", msg.cmd_intterupt.pin_num );
|
|
|
|
if ( ( status = devctl( fd, DCMD_INT_ENABLE_WAIT_PULSE, &msg, sizeof( msg ), NULL ) ) )
|
|
printf( "GPIO control: Error! GPIO DCMD_PULSE devctl failed; status = %d\n", status );
|
|
else
|
|
{
|
|
printf( "GPIO control: Client is waiting for pulses...\n" );
|
|
printf( "GPIO control: Client: chid %d coid %d \n", chid, coid );
|
|
|
|
while ( 1 )
|
|
{
|
|
// wait for the pulse from the resource manager
|
|
MsgReceivePulse( chid, &pulse, sizeof( pulse ), NULL );
|
|
printf( "GPIO control: Client pulse code %d recieved. GPIO interrupt from PIN %u \n\n", pulse.code, pulse.value.sival_int );
|
|
// break;
|
|
}
|
|
|
|
if ( ( status = devctl( fd, DCMD_INT_DISABLE, &msg, sizeof( msg ), NULL ) ) )
|
|
printf( "GPIO control: Error! GPIO DCMD_INT_DISABLE devctl failed; status = %d\n", status );
|
|
else
|
|
printf( "GPIO control: GPIO Interrupt test complete \n" );
|
|
}
|
|
}
|
|
|
|
close( fd );
|
|
|
|
return (EXIT_SUCCESS);
|
|
}
|