Thread: Segmentation Fault - Trying to access parallel port

  1. #1
    Registered User
    Join Date
    Feb 2006
    Location
    Sydney, Australia
    Posts
    40

    Segmentation Fault - Trying to access parallel port

    Hello again,

    I am hoping someone will be able to help me out here.

    I am currently in week 14 of a basic C course and a few weeks ago we built little circuit boards with LEDs and a 7-segment display on them. These boards connect to the parallel port on the box and we write programs to do funky things with the LEDs (eg. convert binary to decimal, display the output of calculations, etc).

    The rest of the class is using Windows and Dev-C while I am using Linux (fedora core 4) and GCC command line (actually, I normally use Xcode and MacOSX but the Mac doesn't have a parallel port so I am using my linux box for the exercises that require the parallel port).

    The teacher wrote instructions for the class on how to install the correct header files to access the port and has given us a test program (a simple binary to decimal converter) to test our boards. However, the instructions and the code were written with the assumption that everyone would be using Windows and Dev-C.

    Here is the program...

    Code:
    #include <stdio.h>
    #include <ioports.h>
    
    /* NOTE:
    Don't forget to add the -l ioports option under 
    Tools->Compiler options
    
    OR from the command line:
    
            gcc binary.c -l ioports -o binary.exe
    */
    
    /* Define which port to write to */
    #define IO_PORT 0x378
    
    main(void)
    {
       int num;
       char instr[25];
    
       printf("press ctrl-C to stop\n\n");
    
       /* Place port into standard output mode */
       outb(IO_PORT+2, inb(IO_PORT+2) & ~32);
    
       while (1) {
          printf("Enter a number (prefix with 0x for hex) :");
          fgets(instr, sizeof(instr), stdin);
    
          /* Jump out of loop if q entered */
          if (toupper(instr[0]) == 'Q')
             break;
    
          sscanf(instr, "%i", &num);
    
          /* now output it to the port */
          outb(IO_PORT, num);  /* write value to port */
       }
       return(0);
    }
    I have had to make a change or two to the code above due to the fact that I am using Linux instead of Windows. After some research I found that I needed to substitute the line that says...
    Code:
    #include <ioports.h>
    for...
    Code:
    #include <sys/io.h>
    because, as I understand it, Linux and Windows use different header files to access their ports. Assuming that this is correct and I have made the correct changes, so far so good (incidentally, if anyone can tell me if I have done this correctly I'd appreciate the feedback as I am working somewhat in the dark. My knowledge in this area is thin at best).

    However, when I run the program I get a segmentation fault.

    I am not sure exactly what is causing this but I did a bit more research and it seems that seg faults usually occur when you are trying to access a chunk of memory illegally. Once I found that out, I suspected that the problem was probably this line...
    Code:
    #define IO_PORT 0x378
    I'm not 100% sure what this does but I have a hunch that it tells the program where the start address of the parallel port is. Sound likely?

    If that is the case, I suspect that the teacher has put that address into the code because that is the address that the parallel port starts at under Windows. Of course, I am using Linux so it is incorrect for me and therefore causes a segmentation fault.

    Can anyone tell me whether or not this is a likely hypothesis or not?

    Assuming I have deduced correctly, can anyone tell me what address Linux uses as the start address for it's parallel port? Failing that can anyone point me to a source where I could find out?

    I apologise if I've made some silly assumptions or come to some boneheaded conclusions in any of the above. As I have said, my knowledge in this area is very very thin and I'm having a real hard time just trying to fit it all together.

    Any and all help gratefully appreciated.

    Cheers,
    TV

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > outb(IO_PORT+2, inb(IO_PORT+2) & ~32);
    Direct access to the hardware is wrong in either OS (shame on your teacher). The fact that windows lets you get away with it doesn't help either.

    > http://people.redhat.com/twaugh/parport/html/ppdev.html
    Basically, you use open() and close() to get access to the driver
    Use ioctl() to set the port into whatever seems to be the best mode.
    Also use ioctl() to drive the various control lines.
    Use read() and write() to drive the data lines.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  3. #3
    Registered User
    Join Date
    Feb 2006
    Location
    Sydney, Australia
    Posts
    40
    Quote Originally Posted by Salem
    > outb(IO_PORT+2, inb(IO_PORT+2) & ~32);
    Direct access to the hardware is wrong in either OS (shame on your teacher). The fact that windows lets you get away with it doesn't help either.

    > http://people.redhat.com/twaugh/parport/html/ppdev.html
    Basically, you use open() and close() to get access to the driver
    Use ioctl() to set the port into whatever seems to be the best mode.
    Also use ioctl() to drive the various control lines.
    Use read() and write() to drive the data lines.

    DAMMIT! Yet again my teacher has let me down. I am really not happy with him at all.

    Oh well, only another 3 weeks and the course is ended. Needless to say, I don't think I'll continue on to do his advanced course.

    Thanks Salem (yet again) for pointing me in the right direction. I will do some reading and see if I can figure it out.

    Thanks,
    TV

  4. #4
    Registered User
    Join Date
    Feb 2006
    Location
    Sydney, Australia
    Posts
    40
    Hello again,

    Thanks for that link Salem, I read it thoroughly but, while it did help me a bit, a lot of it was over my head.

    I spent a few hours going through any man pages that Salem mentioned or that looked relevant (ioctl, ioctl_list, open, close, read, write) and took a look at any of the header files that looked relevant in /usr/include/linux/ (I looked at ioctl.h, ioport.h, parport.h, ppdev.h) but it wasn't much help since a lot of the info seemed to relate to files, not the parallel port and, as I mentioned, I don't have enough background knowledge to understand it all properly. Even the description of the prototype for the ioctl function was over my head (I read the man page 4 times but still couldn't fully get my head around it).

    So, unfortunately, due to my lack of background knowledge, particularly of pointers and access of memory addresses, I am still pretty unenlightened. We just haven't covered any of this stuff in class yet.

    A thought occured to me that perhaps my teacher knows that we have not yet learnt enough to be able to understand the proper way to access the parallel port and so is bending the rules a bit and accessing the hardware directly so that, even though it is not good practice, it is easier for us to understand. Accessing the port directly seems to be simpler to me (although, obviously I can see why it would cause problems and is therefore not good practice).

    Still, I'd like to learn how to do it properly but, without the necessary background knowledge, I'm a bit stuck and these assignments are due next week. As I see it I have 2 options...

    1) Do it the simple and dirty way and try to adjust the memory addresses so that my teacher's windows code works for my Linux box - Problem is, I'm not even sure if that's what the problem is or if adjusting the memory address will fix it. Besides, I've got no idea how to go about finding the correct address.

    2) I try to find a source of info that I can get my head around and learn to do it properly - This is by far my preferred path but I'm not sure I can find such a source. That is, unless...

    I know that asking people to write code for them is a no-no on this forum but I wonder if it is acceptable to ask someone to knock up a short fragment (or fragments) of code that could act as an example for me?

    All I need to do is to turn the individual wires of the parallel port on or off. I'm not sure if it is necessary to initialize the port in some way before you can set the wires (the info I have read seems to suggest that I need to "claim" the port in some way) but, if that is required, I'll also need to do that.

    I don't need to do anything fancy like handshake with a IEEE compliant device or anything, I'm just turning LEDs on and off on a board that I knocked up myself. There is no feedback from the board, the port will be doing all the work. Pins 2 to 9 are connected directly to LEDs and when the wires go on, the LED lights up. Wire goes off, LED goes off, simple as that.

    If I can see a snippet of code that shows me exactly what I need to write in order to turn the wires on and off, I can then do some frobbing and try to work out what is going on.

    Any chance that someone can get me to that point?

    Thanks in advance,
    TV

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. segmentation fault... first time with unix...
    By theMethod in forum C Programming
    Replies: 16
    Last Post: 09-30-2008, 02:01 AM
  2. Re: Segmentation fault
    By turkish_van in forum C Programming
    Replies: 8
    Last Post: 01-20-2007, 05:50 PM
  3. Com port access in two threads..
    By Roaring_Tiger in forum C Programming
    Replies: 1
    Last Post: 04-24-2003, 04:15 AM
  4. Low level access to parallel ports under win2k
    By Incubus in forum Windows Programming
    Replies: 1
    Last Post: 04-23-2002, 01:52 AM
  5. segmentation fault and memory fault
    By Unregistered in forum C Programming
    Replies: 12
    Last Post: 04-02-2002, 11:09 PM