QNX I/O Programming

本文介绍了一种使用并行端口生成1kHz方波的方法。通过配置并行端口的控制寄存器,并利用定时器触发信号来翻转输出状态,实现稳定的1kHz方波输出。文中还包含了必要的代码示例。

https://code.google.com/p/rt-embedded-project6/source/browse/trunk/Project3.c?r=6

http://rt-embedded-project6.googlecode.com/svn-history/r6/trunk/Project3.c

/**********************************************************************
 * Project3.c
 *
 * Configures the parallel port to generate a 1kHz square wave.
 *
 * Authors:
 * 		Sajin George
 * 		Russ Martin
 * 		Oliver Wing
 *
 * Credit to http://psy.swan.ac.uk/staff/carter/qnx/tut_nto_parout.htm 
 * for the otherwise very tricky setup of the parallel port for output.
 */

#include <stdlib.h>
#include <stdio.h>
#include <unistd.h> 		// for sleep()
#include <stdint.h>
#include <time.h>
#include <hw/inout.h> 		// for in*() and out*() functions
#include <sys/neutrino.h>	// for ThreadCtl()
#include <sys/mman.h>		// for mmap_device_io()
#include <sys/siginfo.h>	// for sigevent and signal handling
#include "types.h"

/* The Neutrino IO port used here corresponds to a single register, which is
 * one byte long */
#define PORT_LENGTH 1
/* The first parallel port usually starts at 0x378. Each parallel port is
 * three bytes wide. The first byte is the Data register, the second byte is
 * the Status register, the third byte is the Control register. */
#define DATA_ADDRESS 0x378
#define CTRL_ADDRESS 0x37a
/* bit 2 = printer initialisation (high to initialise)
 * bit 4 = hardware IRQ (high to enable) */
#define INIT_BIT 0x04

// One-bit constants.
#define LOW 0x00
#define HIGH 0xFF
// Arbitrary test value for post. Can be any byte
#define TEST_VAL 0x55


/* Clock resolution in nanoseconds. Must be less than or equal to 500 us for
 * the 1kHz clock to properly be generated.*/
#define CLOCK_RESOLUTION 500000

// Variables that control the square wave.
bool outputHigh = false;
bool portInitialized = false;
uintptr_t data_handle;

/* Flip the output bits.
 * Param: signo: ID of signal that generates the call to this method
 * 					This is unused, but required by signal/event handler
 */
void FlipOutput(int signo)
{
	if (portInitialized) {
		if (outputHigh) {
			out8( data_handle, LOW );
			outputHigh = false;
		}
		else {
			out8( data_handle, HIGH );
			outputHigh = true;
		}
	}
}

// Power-on self test functions.
bool POST() {
	UINT8 testIn;
	//write a bit out to register
	out8(data_handle, TEST_VAL);
	//now read in; the parallel port is write-only,
	//but reading it will return the last byte sent
	testIn=in8(data_handle);
	//fail if not equal to byte sent
	return(testIn==TEST_VAL);
}

int main(int argc, char *argv[]) {

	// Control register for parallel port
	uintptr_t ctrl_handle;

	// Structs and values needed for timer and event handler
	struct sigevent event;
	timer_t timer2KHz;
	struct itimerspec timerInfo;
	struct _clockperiod clockResolution;

	// Give the thread root permissions to access the hardware
	if ( ThreadCtl( _NTO_TCTL_IO, NULL ) == -1 )
	{
		fprintf( stderr, "Can't get root permissions!\n" );
		return -1;
	}

	// Set the clock resolution to something below 500 usec.
	clockResolution.nsec = CLOCK_RESOLUTION;
	clockResolution.fract = 0;
	if ( ClockPeriod( CLOCK_REALTIME, &clockResolution, NULL, 0 /* unimportant parameter */ ) == -1 )
	{
		fprintf( stderr, "Clock not allowing the necessary resolution change!\n" );
		return -1;
	}

	// Get a handle to the parallel port's Control register
	ctrl_handle = mmap_device_io( PORT_LENGTH, CTRL_ADDRESS );

	// Initialise the parallel port
	out8( ctrl_handle, INIT_BIT );

	// Get a handle to the parallel port's Data register
	data_handle = mmap_device_io( PORT_LENGTH, DATA_ADDRESS );

	// Set up a basic signal notification to trigger SIGUSR1.
	SIGEV_SIGNAL_INIT ( &event, SIGUSR1 );

	// Connect a timer to the signal notification.
	timer_create( CLOCK_REALTIME, &event, &timer2KHz );

	// Everything's ready to go.
	portInitialized = true;

	// Run POST tests.
	if ( POST() )
	{
		// Everything passed!
		printf( "POST successful!\n" );
	}
	else
	{
		// Something is wrong.
		printf( "POST failed!\n" );
		return -1;
	}

	// Install the timer signal handler.
	signal( SIGUSR1, FlipOutput );


	/* Set up the timer to trigger a signal once every 500 us (twice per cycle).
	 * Wait 500 us until the first signal, and then 500 us for each future signal. */
	timerInfo.it_value.tv_sec = 0;					// Timer period div 1E9 nsec
	timerInfo.it_value.tv_nsec = CLOCK_RESOLUTION;	// Timer period mod 1E9 nsec
	timerInfo.it_interval = timerInfo.it_value;		// Timer is pure periodic
	timer_settime( timer2KHz, 0 /* relative time */, &timerInfo, NULL );

	// Wait for and process signals as they arise.
	for ( ;; )
	{
	}

	return 0;
}

转载于:https://www.cnblogs.com/zhhkang/p/3745353.html

Operating Systems Courses in operating systems cover the design of the components of an operating system—scheduler, memory manager, file system, etc. Only a small fraction of programmers ever write this kind of code, though. On the other hand, they can access many features of the OS using system calls such as fork, wait, exec, etc. This level of programming is not generally covered in any course. In Chapter 8, we describe process management, and how programmers can make use of the process control features of Unix and Linux. Other Topics We cover a wide range of systems topics, all from a programmer's perspective. Besides those mentioned above, these include machine-level programming, optimizing compilers, processor architecture, linking, performance measurement, virtual memory, I/O, network programming and concurrency. In viewing what to cover about a subject and how to present it, we have used the filter “How could a sophisticated application programmer make use of this material?” Key Points The material in this book has direct value for programmers. Students find that it explains many of the mysterious problems they've already encountered, that it helps them write and debug code more efficiently, and that their programs are more reliable and efficient. Even if this is the only systems course they ever take, they will have achieved a higher level of competence than many entry-level programmers. The material in this book is unique. Much of it is not presented in any other book or taught in previous courses. Instead, a traditional coverage of systems requires programmers to figure out on their own how the characteristics of the systems they study in builder-centric courses can be exploited to improve their programs. Programmers must struggle through confusing Unix man pages or read advanced systems programming books just to use the simple process control functions provided by Unix. The book provides a solid foundation for builder-centric courses. We believe that more advanced systems courses should present systems from a builder's perspective. Students will be much better oriented to the needs and constraints of these systems by first studying them from a programmer's perspective. At Carnegie Mellon, our Introduction to Computer Systems course has become a prequisite for courses in both CS and ECE covering: operating systems, networking, compilers, computer graphics, computer architecture, and embedded system design. Copyright © 2011, 2015 Randal E. Bryant and David R. O'Hallaron翻译以上英文为中文
08-25
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值