LinuxQuestions.org
Review your favorite Linux distribution.
Home Forums Tutorials Articles Register
Go Back   LinuxQuestions.org > Forums > Non-*NIX Forums > Programming
User Name
Password
Programming This forum is for all programming questions.
The question does not have to be directly related to Linux and any language is fair game.

Notices


Reply
  Search this Thread
Old 03-22-2007, 04:34 PM   #1
cyb0rg777
Member
 
Registered: Dec 2004
Location: ~
Distribution: Debian
Posts: 143
Blog Entries: 8

Rep: Reputation: 15
8253 timer


I am writing some programs that interface with hardware in assembly.I really need a timer that goes to at least 1ms .Even lower would be better. The only thing I can come up with is assembly language programming of the 8253 timer,but I can't seem to figure it out.Here is a simple program I'm trying to write to test the timer.

Code:
#include <stdio.h>
void timer8253(void);
int read8253(void);
void zero8253(void);
int main()
{
int time;
while(1)
{
timer8253();
sleep (1);
printf("coutnt =%d",read8253());	
}	
	
}

void timer8253(void)
{
	asm("cli");			//disable hardware interrupts
	outb(0x76,0x43);     //send mode to mode register               
	outb(0xFF,0x41);     //set lsb	
	outb(0xFF,0x41);     //set msb
	asm("sti");			//enable hardware interrupts
}



int read8253(void)
{
	int time=0;
	// reads the time in ticks into CounterValue
	asm(
    "xor     %eax,%eax \n\t"
    "in      $0x41,%al \n\t"         //least significant byte
    "jmp (+2) \n\t"//    QDELAY
    //"jmp $+2 \n\t"
    "mov	%al,%ah \n\t"
    "in	$0x41,%al \n\t"	//most significant byte
    "xchg	%al,%ah \n\t"
    "mov     $0xffff,%ebx \n\t"
    "sub     %eax,%ebx \n\t"
    "mov     %ebx,%0 \n\t"
	:"=a"(time)
	:%eax,%ebx	
	); 
	//code :output :input :used registers
    zero8253();
	return time;

}
void zero8253(void)
{
    //actually sets counter to ffffh
     asm(
	"jmp (+2) \n\t"
	"mov     $0x0ff,al \n\t"
	"out	%al,$0x40 \n\t"
	"jmp (+2)\n\t"
 	"out	%al, $0x40"
	:%eax
	);
}
The assembly code won't build at all.
Here is where I got all of my info.

http://www.google.com/codesearch?hl=...=QTIMER.ASM#a0
http://asm.sourceforge.net/articles/...inline-asm.txt

And a few other sources.
This at&t inline assembly stuff is HARD .
If you think that's funny please tell me how simple the answer is!
 
Old 03-22-2007, 06:04 PM   #2
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
You are correct about the unwieldy syntax for the inline assembler. Since you are intent on playing with hardware at this low level, I'll assume you are not planning to run this under Linux, or other protected mode OS (if you are, then your problems are just beginning...). So, since you are programming right to the metal, why not use a cross assembler, such as NASM and generate DOS executables, or executables that run standalone? Is this intended to even run on a PC architecture at all, or on some other x86 pltform?

More specific to your problem, a question? Are you planning to generate interrupts, or just tickle some hardware? On a PC, the Channel 1 that your code is accessing will play havoc with RAM refresh, and may well crash any modern PC. Some oldies, like '286 & '386 architectures tended to be tolerant of this kind of pokery, but I wouldn't count on that with today's designs. If you want to generate interrupts at 1KHz, you will need to use channel 0, and write 04h to the MSB, and A9h to the LSB. This will result in a 1.5% error, due to the clock frequency not being an exact integer multiple of 1000. Handling the interrupts may require managing the 8259 Interrupt Controller, along with of course, invoking whatever it is you want to do 1000 times per scond.

I used to do this kind of stuff with my eyes closed, but its been so many years, I don't remember all the details. Tell me a little more about the architecture and purpose of your adventure, and I'm sure I can help. I will scan some old disks and what-have-you tonight, and see if I can't come up with some old working code.

--- rod.

PS. Please tell me this is not your homework.

Last edited by theNbomr; 03-22-2007 at 06:07 PM.
 
Old 03-22-2007, 07:24 PM   #3
cyb0rg777
Member
 
Registered: Dec 2004
Location: ~
Distribution: Debian
Posts: 143

Original Poster
Blog Entries: 8

Rep: Reputation: 15
Not homework, just a hobby. I need this to time data coming from the parallel port right now, but later I think it will come in handy elsewhere.I really wanted a DOS(Freedos) executable but I wrote the rest of the program already.I was looking for a DOS cross compiler but that's another story.Until I get a C cross compiler to make a DOS executable I'm going to use linux.I just need the timing portion.I really don't want to rewrite everything. I was planning to use it in linux anyway.Are you saying it won't work?I have had this problem on a lot of programs.I need to time the signals but I can't. If I could it would improve a lot of my work, not just this project. Hard to believe with all the megahertz signals inside a pc I can't access one of them for timing.

Could you give me some advice to solve the problem?
The more convenient the better.
Maybe a game library would have these timers for C?
 
Old 03-23-2007, 09:54 AM   #4
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
In Linux, you don't have the liberty of accessing hardware freely like you do in a real-mode OS like DOS. In order to protect itself and other processes, the kernel uses facilties built into the the CPU to prohibit access to hardware and absolute memory addresses. In particular, I think the OS uses the timer interrupt in a PC architecture to invoke the kernel's task switching mechanism on an interrupt driven basis (as distinct from an OS like Windows, which is primarily a cooperative multitasking OS, AFAIK). Linux does provide it's own source of high resolution timers available through system calls. Do man gettimeofday for details on one of them.

Have you looked at the port of DJGPP to Linux as a DOS targeted compiler that runs under Linux?

I did manage to dig out a DOS MASM compatible source file that seems to do what you want. It assembles to a MS C-callable object module that allows you to speed up the 8253 timer interrupt by an arbitrary power of 2, and provides hooks to allow it to update a counter variable at the accelerated rate. It's a bit long, so I'm loath to post it here, but if you think it would be helpful, I could get it to you another way. If any moderators are listening, maybe they could comment on guidleines for this sort of thing.

--- rod.
 
Old 03-23-2007, 09:52 PM   #5
cyb0rg777
Member
 
Registered: Dec 2004
Location: ~
Distribution: Debian
Posts: 143

Original Poster
Blog Entries: 8

Rep: Reputation: 15
As a matter of fact I have looked at that cross compiler.
Right here is where you get the RPM package to install it.

ftp://ftp.delorie.com/pub/djgpp/rpms/

It would be a great match to have Linux as a development environment for freedos.
I've been busy doing other stuff though.
I think I have a way to read the signal ,but I still need that timer.
Here is what I'm trying now.
Code:
here is what the sgnals look like.
_   ____
 | |    |  =0
 |_|    |
 S      S

_      _
 |    | |  =1
 |____| |
 S      S

So a one is at least ten times longer low from start to stop.

for(int i=0;i<9;i++)
{
while(port is high)high++;
while(port is low)low++;
if (high >10*low)byte|(1<<i);
}
What do you think?
I'm still working on the timing.
I have other applications for the timer even if I don't need it here.
I don't think I will go with that assembly code.
Thanks for explaining it to me anyway.
If there was a way to time a loop maybe?
 
Old 03-24-2007, 07:17 AM   #6
jlinkels
LQ Guru
 
Registered: Oct 2003
Location: Bonaire, Leeuwarden
Distribution: Debian /Jessie/Stretch/Sid, Linux Mint DE
Posts: 5,195

Rep: Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043
cyb0rg,

This is never gonna work in plain Linux. First you cannot talk to the hardware directly, secondly the kernel might dedicate its time to another task instead of yours and you might never know it.

You either have to switch to RT Linux or to writing a device driver. RT Linux is nice, but you'll have to dedicate your entire machine to the task. A device driver can communicate with the hardware in real-time and that might be what you need. But I think writing a device driver is difficult if you don't have a starting point in the form of an existing driver.

You might want to look into the Comedi libraries. Small timing delays are implemented with usleep() which are perfect for the timing intervals you are looking for. I am not sure whether there is a Comedi driver for the parallel port. If not it might give you a starting point though.

What you say about you preference of having a DOS app is true. I wrote many control programs in DOS. However I came to prefer writing them in Linux using Comedi, even using the same hardware.

jlinkels
 
Old 03-24-2007, 10:52 AM   #7
cyb0rg777
Member
 
Registered: Dec 2004
Location: ~
Distribution: Debian
Posts: 143

Original Poster
Blog Entries: 8

Rep: Reputation: 15
Thanks for the reply ,
The comedi drivers look like they might work. I'll look into them a bit.
I'm using some really old computers (166mhz) to do my tests.
I have slackware installed on one and vector linux on another.
I don't think there is a distribution of RT linux that would replace those?


What about the code example I posted ,it should work ,right?
 
Old 03-24-2007, 12:06 PM   #8
jlinkels
LQ Guru
 
Registered: Oct 2003
Location: Bonaire, Leeuwarden
Distribution: Debian /Jessie/Stretch/Sid, Linux Mint DE
Posts: 5,195

Rep: Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043Reputation: 1043
Quote:
Originally Posted by cyb0rg777
Thanks for the reply ,
The comedi drivers look like they might work. I'll look into them a bit.
I'm using some really old computers (166mhz) to do my tests.
Are you kidding? I developed my first Comedi application om a P166. 2x8 bit digital I/O and 2 channels analog, sampled and processed that with a 5 ms clock and never even noticed processor load.

Quote:
Originally Posted by cyb0rg777
I have slackware installed on one and vector linux on another.
I don't think there is a distribution of RT linux that would replace those?
Yes, it replaces your distro That is, you put RT linux on it and you don't have another distro installed anymore and you can't do real work on the either.

The decision whether you use RTLinux or Comedi device drivers is whether you need guaranteed response time. And I don't mean on the driver level. You do have guaranteed times to measure useconds etc. Guaranteed response is after your application reads the bytes from the driver, your need a minimum response time. For example if you detect overcurrent, and you'd have to decide to open a switch. You need RTL for that. If you can wait 100-200 ms worst case (like switching on an indicator in a user panel) Comedi is fine. I never saw response times over 50 ms on a P700 running Debian (w/o GUI that is)


Quote:
Originally Posted by cyb0rg777
What about the code example I posted ,it should work ,right?
Not in Linux, but perhaps in DOS. I am not good in code tracing, I use gdb an see what happens

jlinkels
 
Old 03-24-2007, 02:54 PM   #9
theNbomr
LQ 5k Club
 
Registered: Aug 2005
Distribution: OpenSuse, Fedora, Redhat, Debian
Posts: 5,399
Blog Entries: 2

Rep: Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908Reputation: 908
Timing loops are a poor way to do measurements, even under a quasi-OS like DOS, which does have all sorts of things going on that consume arbitrary amounts of CPU as interrupt handlers.

A better algorithm would seem to be, something like:
Code:
foreach bit{
    loop( while no start edge )
    grab time[start]
    loop( while no data edge )
    grab time[data]
    loop( while no stop edge )
    grab time[stop]
    if( ( time[stop] - time[data] ) < 10 * ( time[data] - time[start] ) ) then
        bit = 1
     else
        bit = 0
     endif
}
The 'grab time' statement would be the part where you either read a hardware timer, or get some measure of time from the OS, like gettimeofday() as I suggested earlier. This will probably be quite reliable on signals where a bit time is in the order of 100s of microseconds or longer, even on a non-realtime OS. If you have a realtime OS, you might simply spawn a periodic task to read the data line level (perhaps doing multiple reads per interval, for noise immunity), and use the periodicity of the task timing to measure time.

--- rod.

Last edited by theNbomr; 03-24-2007 at 02:56 PM.
 
Old 04-07-2007, 06:12 PM   #10
cyb0rg777
Member
 
Registered: Dec 2004
Location: ~
Distribution: Debian
Posts: 143

Original Poster
Blog Entries: 8

Rep: Reputation: 15
I have read up a little and decided that rtai would be a good choice.
I have it installed and I'm looking for documentatoin and examples on it now.
 
  


Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off



Similar Threads
Thread Thread Starter Forum Replies Last Post
Multimedia timer (SMP friendly timer) bigqueso Linux - Kernel 0 03-15-2007 03:49 PM
About timer.... help rajsun Programming 3 05-24-2005 06:06 AM
timer in c?? AcidHell2 Programming 9 08-12-2004 01:01 AM
First timer, help!!!!! jcniest5 Linux - Newbie 7 02-24-2004 08:32 AM
timer... perdesiz Linux - Software 1 09-18-2003 03:39 AM

LinuxQuestions.org > Forums > Non-*NIX Forums > Programming

All times are GMT -5. The time now is 04:06 PM.

Main Menu
Advertisement
My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
Open Source Consulting | Domain Registration