Hi, 

I have some questions about the linux kernel and the mainframe of my driver
(They still not working but I believe... ) If someone have time, he can
continue my learning!

1- What is the read (readb (8bits), readw (16 bits), ... (32bits)) function
(read memory mapped PCI) for a unsigned integer 32bits ? readdw?

2- What is the key word "volatile" in C? It's not wrote in my C book.

3- Before configure my timer/counter 82C54, I need a time delay. I actually
 use rtl_delay. My task is not critical (during the configuration) can use
a since sleep in the rtl process?

4- I will use a thread for driver the communication/control of my ISR (I
will add other functionalitys later, the source code is in attachment but
not working/not tested/not compiled). I do this because the IRQ is timed by
the device (data acquisition board). This process need to be real-time...
but with a very low priority. How work the priority? by relative priority
level (as in java)? Can I make the setup of this rt-thread with the same
priority as the other none rt-thread?

5- Where is the declaration of the structure sched_param? I am interest to
look at setup possibility.

Thanks a lot,
I appreciate your help.

Stephane Bouchard
[EMAIL PROTECTED]

  

/* ************************************************************************ */
/*           ComputerBoard PCI-DAS1602/16 DAQ Board Driver                  */
/* Stephane Bouchard                                                        */
/* [EMAIL PROTECTED] / [EMAIL PROTECTED]                                */
/* Laboratoire de Recherche en BioIngenierie                                */
/* Universite Laval, Quebec, Canada                                         */
/*                                                                          */
/* Special thanks to all people from RT-Linux mailing list                  */
/* only the need functionality for my project is implemented... you can     */
/* continue.                                                                */
/* ************************************************************************ */

#include <linux/pci.h>
#include <linux/version.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <asm/io.h>

#include <rtl_core.h>
#include <trl_time.h>
#include <rtl_sched.h>
#include <rtl_fifo.h>
#include <rtl_sync.h>

#include "common.h"

/* ************************************************************************ */ 
/* global variables                                                         */
/* ************************************************************************ */

static struct BoardInfo board;
static union intReg intRegStatus;
static uint16 *dataRead=NULL;
static uint32 countIRQ;
pthread_t thread;
uint32 numberscan;
uint8 countChannel;
uint16 regIntCp;

/* ************************************************************************ */ 
/* global variables and macro commands for FP operation in ISR              */
/* ************************************************************************ */

uint32 cr0;
uint32 linux_fpe[27];
uint32 task_fpe[27];

#define save_cr0_and_ctls(x) __asm__ __volatile__ ("movl %%cr0,%0; clts" :"=r" (x))
#define restore_cr0(x)       __asm__ __volatile__ ("movl %0,%%cr0": :"r" (x))
#define save_fpenv(x)        __asm__ __volatile__ ("fnsave %0" : "=m" (x))
#define restore_fpenv(x)     __asm__ __volatile__ ("frstor %0" : "=m" (x))


/* ************************************************************************ */ 
/* volatile void CBISR();                                                   */
/* This function is call by the interrupt                                   */
/* args in          :                                                       */
/* args out         :                                                       */ 
/* global variables : struct BoardInfo board                                */
/*                    fifo                                                  */
/* Note:                                                                    */
/* ************************************************************************ */      

volatile void CBISR() {

    /* disable the irq of the device during the isr */
    rt_disable_irq(board.irq);

    /* look if the interrupt come from this board */
    if (!readdw(board.badr0+0x00000038)&0x00820000) {

        /* Start of floating point operation */
        save_cr0_and_ctls(cr0); 
        save_fpenv(linux_fpe);
        restore_fpenv(task_fpe);

        /* read the datas from register */
        for (countChannel=0;countChannel<CHANNELNUMBER;countChannel++) {
                 dataRead[countChannel]=(uint16)(readw(board.badr2)*0.5);
                };
                 
                /* put controller and out here */

      
        /* Stop of floating point operation */
        save_fpenv(task_fpe);
        restore_fpenv(linux_fpe);
        restore_cr0(cr0);

        /* send data out by the fifo */
        rtf_put(FIFO_data, dataRead, CHANNELNUMBER*2);

        /* check the number of scan and ... */
        if (countIRQ<numberscan) {
                 /* increase the number of scan */
                 countIRQ++;
                 /*clear the interrupt */
                 writew(0x0085, board.badr1);
                } else {
                /* stop pacer */
            writew(0x0000,board.badr1+0x0002);
            
            /* clear ADC fifo */
            writew(0x0000,board.badr2+0x0002); /* write junk */
                };

    };

    /* enable the irq of this device */
    rt_enable_irq(board.irq);

    /* share irq with linux and other devices */
    rtl_pend_linux_irq(board.irq)
};

/* ************************************************************************ */
/* int16 CBFind(void);                                                      */
/* This function look for the board. If find, set all information in struct */
/* BoardInfo board.                                                         */
/* args in          :                                                       */
/* args out         : int16 status                                          */
/*                    status : status of the function                       */ 
/* global variables : struct BoardInfo board                                */
/* ************************************************************************ */         
                        

int16 CBInit() {
    
     extern struct pci_dev *pdev=NULL;

     /* Check if a pci bus is present */
     if (!pci_present()) {
          return NOPCIBUS;
     };

     /* look for a ComputerBoards PCI-DAS1602/16 */
     if pdev=pci_find_device(VENDORID, BOARDID, pdev)) {

          /* Map the pci memory in the cpu memory */
          board.badr0=(uint32 *) ioremap(pdev->base_address[0], 0x0004 );
          if(board.badr0==NULL) return IOREMAPERR;  
          board.badr1=(uint16 *) ioremap(pdev->base_address[1], 0x000A);
          if(board.badr1==NULL) return IOREMAPERR;
          board.badr2=(uint16 *) ioremap(pdev->base_address[2], 0x0004);
          if(board.badr2==NULL) return IOREMAPERR;
          board.badr3=(uint8 *) ioremap(pdev->base_address[3], 0x000D);
          if(board.badr3==NULL) return IOREMAPERR;
          board.badr4=(uint16 *) ioremap(pdev->base_address[4], 0x0004);
          if(board.badr4==NULL) return IOREMAPERR;

          /* setup informations in the struct BoardInfo board */
          board.irq=pdev->irq;
          board.vendorID=VENDORID;
          board.boardID=BOARDID;

     } else {
          return NOPCIDAS160216;
     };
};

/* ************************************************************************ */ 
/* int16 CBConfigure(double frequency);                                     */
/* This function configure the board and set the frequency                  */
/* args in          : double frequency                                      */
/*                    frequency : sampling frequency of the board           */
/* args out         : int16 status                                          */
/*                    status : status of the function                       */ 
/* global variables : struct BoardInfo board                                */
/* ************************************************************************ */      

int16 CBConfigure(double frequency) {

     /*allocate to backup the irq lines status */
     rtl_irqstate_t irqStatus;

     /* disable interrupts on the CPU */
     rtl_no_interrupts(irqStatus);

     /* configure the isr handler and get the interrupt */
     if(!rtl_request_irq(board.irq, &CBISR)) {

          /* setup variable for make the computation of the diviser frequency */
          uint32 diviserFrequency;
          uint8 *diviserFreq;     
          diviserFreq=&diviserFrequency;
    
          /* disable everything first */
          writew(0x0000,board.badr1)
    
          /* stop pacer */
          writew(0x0000,board.badr1+0x0002);

          /* clear ADC fifo */
          writew(0x0000,board.badr2+0x0002); /* write junk */
 
          /* setup pacer for internal pacer clock */
          /* 8254 - counter 1 mode 2 least significant bit */
          writeb(0x0054,board.badr3+0x0003);
          rtl_delay(10);
          /* 8254 - counter 2 mode 2 least significant bit */
          writeb(0x0094,board.badr3+0x0003);
          rtl_delay(10);

          /* compute the diviser for 82C54 (Pacer source at 10Mhz and 8 channels)*/
          diviserFrequency=(long)(10000000/frequency);

          /* write the ADC pacer diviser for generate the frequency */
          writeb(*(diviserFreq+4),board.badr3+0x0001); /* 0-7 bits   */
          rtl_delay(10);
          writeb(*(diviserFreq+3),board.badr3+0x0001); /* 8-15 bits  */
          rtl_delay(10);
          writeb(*(diviserFreq+2),board.badr3+0x0002); /* 16-23 bits */
          rtl_delay(10);
          writeb(*(diviserFreq+1),board.badr3+0x0002); /* 24-32 bits */
          rtl_delay(10);

          /* configure the dio */
          /* port A out, port B in, port C up out, port C low in */
          writeb(0x0082,board.badr3+0x0007); 

          /* setup trigger control */
          /* No trigger set, burst mode select 10Mhz source fro counter 0*/
          writew(0x0020,board.badr1+0x0004);

          /*enable the acquisition interrupt */
          writew(0x0005, board.badr1);

          /* setup the irq as real-time irq */
          rtl_hard_enable_irq(board.irq);   

      } else {
              return IRQREQUESTERR;
      };

      /* restore the interrupts for the cpu */
       rtl_restore_interrupts(irqStatus);

       return NOERROR;
};

/* ************************************************************************ */ 
/* int16 CBStart();                                                         */
/* This function start the acquisition and the control loop                 */
/* args in          :                                                       */
/* args out         : int16 status                                          */
/*                    status : status of the function                       */ 
/* global variables : struct BoardInfo board                                */
/* ************************************************************************ */      

int16 CBStart() {

    /*reset the number of int loop */
    countIRQ=0;

    /* clear ADC fifo */
    writew(0x0000,board.badr2+0x0002); /* write junk */

    /* setup the MUX and the control register */
    /* diff +/- 5 Volts, internal 82C54 Counter/Timer (10 Mhz) */
    /* and 8 channels */
    writew(0x1170,board.badr1+0x0002); 
 
    return NOERROR;
};

/* ************************************************************************ */ 
/* int16 CBStop();                                                          */
/* This function stop the acquisition and the control loop                  */
/* args in          :                                                       */
/* args out         : int16 status                                          */
/*                    status : status of the function                       */ 
/* global variables : struct BoardInfo board                                */
/* ************************************************************************ */      

int16 CBStop() {

    /* stop pacer */
    writew(0x0000,board.badr1+0x0002);
    
    /* clear ADC fifo */
    writew(0x0000,board.badr2+0x0002); /* write junk */

    return NOERROR;
};

/* ************************************************************************ */ 
/* int16 CBClose();                                                         */
/* This function close the device, please use CBStop before                 */
/* args in          :                                                       */
/* args out         : int16 status                                          */
/*                    status : status of the function                       */ 
/* global variables : struct BoardInfo board                                */
/* ************************************************************************ */      

int16 CBClose() {

    /* disable the burst mode */
    writew(0x0000, board.badr1+0x0004);

    /* disable the acquisition interrupt */
    writew(0x0000, board.badr1);

    /* free irq */
    if(board.irq!=0) rtl_free_irq(board.irq);

    board.irq=0;

    /* unmap all allocate memory mapped by the precessor*/
    iounmap(board.badr0);
    iounmap(board.badr1);
    iounmap(board.badr2);
    iounmap(board.badr3);
    iounmap(board.badr4);
};

/* ************************************************************************ */  
/* void *CBModuleRT();                                                      */ 
/* This function send order to the interrupt.                               */ 
/* args in          :                                                       */ 
/* args out         :                                                       */ 
/* ************************************************************************ */    
 
void *CBRTModule() { 
 
     uint8 command;     /* command to execute */ 
     double frequency;  /* frequency of the acquisition */ 
     uint32 scan;       /* number of scans to acquire */ 
     uint16 status;     /* status of the command */ 
     struct sched_param param;

     param.sched_priority=1;
     pthread_setschedparam(pthread_self(), SCHED_FIFO, &param);
     pthread_make_periodic_np(pthread_self(), gethrtime(), 50);

     while(1) { 
          pthread_wait_np(); 
           
          switch rtf_get(FIFO_OUT_DATA,&command,sizeof(uint8)) { 
               case CB_CONFIGURE: 
                    rtf_get(FIFO_COMMAND,&frequency,sizeof(double)); 
                    rtf_get(FIFO_COMMAND,&scan,sizeof(uint32)); 

                    /* init the status for compute the number of scan */ 
                    countIRQ=0; 
                    numberscan=scan; 
 
                    /* allocate the space for the read data */  
                    dataRead=kmalloc(dataRead,CHANNELNUMBER,GFP_KERNEL); 
      
                    /* find the PCI DAQ board */ 
                    status=CBInit(); 
                    rtf_get(FIFO_STATUS,&status,sizeof(uint16)); 
 
                    /* configure the PCI DAQ board */ 
                    status=CBConfigure(frequency); 
                    rtf_get(FIFO_STATUS,&status,sizeof(uint16)); 
               return; 
 
               case CB_START: 
                    status=CBStart(); 
                    rtf_get(FIFO_STATUS,&status,sizeof(uint16)); 
               return; 
 
               case CB_STOP: 
                    status=CBStop(); 
                    rtf_get(FIFO_STATUS,&status,sizeof(uint16)); 
               return; 
 
               case CB_CLOSE: 
                    /* disable acquisition */ 
                    CBStop(); 
 
                    /* close the device */ 
                    CBClose(); 
 
                    /* close the fifo */ 
                    rtf_destroy(FIFO_OUT_DAT); 
 
                    /* free the memory */ 
                    if(dataRead!=NULL) kfree(dataRead); 
                return; 
 
               default: 
                    rtl_printf("Real time task unknown"); 
               return; 
          }; 
     }; 
     return 0; 
}; 

/* ************************************************************************ */ 
/* void CBInitModule();                                                     */
/* This function init the module to communicate with display program.       */
/* args in          :                                                       */
/* args out         :                                                       */
/* ************************************************************************ */   

int16 init_module(void) {

    pthread_attr_t attr;
    struct sched_param sched_param;

    /* setup the fifo */
    rtf_destroy(FIFO_COMMAND);
    rtf_create(FIFO_COMMAND,FIFO_COMMAND_SIZE);   
    rtf_destroy(FIFO_STATUS);
    rtf_create(FIFO_STATUS,FIFO_STATUS_SIZE);  
    rtf_destroy(FIFO_OUT_DATA);
    rtf_create(FIFO_OUT_DATA,FIFO_OUT_DATA_SIZE);   

    return pthread_create (&thread, NULL, start_routine, 0);
};

/* ************************************************************************ */ 
/* void cleanup_module(void);                                               */
/* This function clear the communication module.                            */
/* args in                                                                  */
/* args out         :                                                       */
/* ************************************************************************ */
 
void cleanup_module(void)  
    rtf_destroy(FIFO_COMMAND);
    rtf_destroy(FIFO_STATUS);
    rtf_destroy(FIFO_OUT_DATA);

    pthread_delete_np(thread); 
};

     
#ifndef _COMMON_
#define _COMMON_

/* Type ... for non familar with Linux */
#define int8   i8
#define int16  i16
#define int32  i32
#define uint8  u8
#define uint16 u16
#define uint32 u32

/* error list */
#define NOERROR          00
#define NOPCIBUS         01
#define NOPCIDAS160216   02
#define IOREMAPERR       03
#define ERRASIGNISR      04
#define IRQREQUESTERR    05
#define FIFOERR          06
#define DATAREADERR      07

/* define the code number for the inter-process message */
#define CB_CONFIGURE     01
#define CB_START         02
#define CB_STOP          03
#define CB_CLOSE         04

/* ComputerBoards PCI-DAS1602/16 definition*/
#define VENDORID 0x1307
#define BOARDID  0x0001

/* define the fifo */
#define FIFO_OUT_DATA 3
#define FIFO_OUT_DATA_NAME "dev/rtf3"
#define FIFO_OUT_DATA_SIZE 0x1000
#define FIFO_COMMAND 4
#define FIFO_COMMAND_NAME "dev/rtf4"
#define FIFO_COMMAND_SIZE 0x0100
#define FIFO_STATUS 5
#define FIFO_STATUS_NAME "dev/rtf5"
#define FIFO_STATUS_SIZE 0x0100

/* define the number of channel */
#define CHANNELNUMBER 8

/* define a structure to stock the board informations */
struct BoardInfo {
     uint32 *badr0;
     uint16 *badr1;
     uint16 *badr2;
     uint8  *badr3;
     uint16 *badr4;
     uint8   irq;
     uint16  vendorID;
     uint16  boardID;
} board;


#endif

Reply via email to