Driver test on Debian Wheezy

Asked by Claude LARIVIERE

Hello Pierre,
I'm trying to use your driver on Debian Wheezy, it compiles well, i can read the interbus configuration online, but it fails with 0x0701 (SM_START_DATA_TRANSFER_REQ_CODE) request. I notice that a fuction called ibsCyclePrepare can be used in the library, do you have a code example or documentation of bus starting ?
I'm a french C, C++ automation developper, i have to port a Win interbus application to realtime Linux.

Thanks for this great job !

Question information

Language:
English Edit question
Status:
Answered
For:
ibsdrv Edit question
Assignee:
No assignee Edit question
Last query:
Last reply:
Revision history for this message
Pierre Quelin (pierre.quelin) said :
#1

Hello Claude,

thank you for your interest concerning my piece of code.
I developed this driver on my free time to demonstrate the feasibility of porting VxWorks 5.4/6.3 -> Linux (Xenomai).
My intention was to limit the kernel side for reliability and to provide a minimum user library with a generic code.
Unfortunately I do not have a practical example to show you, the application layer is the property of my company. I know that it's not easy, but interbus is not an easy bus and the documentation is not very clear.

Here is a summary of what the application need to do, the cycles are generated every 5 ms by a thread which differs from the "standard" Phoenix use.

----------------------------------------------------------------
main()
{
...
   IBSMASTER m_master;

   // Open the device
   m_master = ibsMasterOpen( "/dev/ibs0" );

// ibsMasterReset( m_master );

// TODO - start a cycle, wait the cycle end, ???

   ibsMasterClose( m_master );
...

}

// To obtain diagnostic information
...
      // Check the master
      unsigned short status = ibsStatusGet( m_master );

      if ( status != ( IBS_DIAG_STATUS_READY | IBS_DIAG_STATUS_ACTIVE | IBS_DIAG_STATUS_RUN ) )
      {
         unsigned short param = ibsParamGet( m_master );
         // TODO - "Cycle diagnostic : %04x %04x", status, param );
      }

...

// Start a cycle
...
   // Copy the output process data to the MPM
   ibsDataWrite( m_master, pdOut, pdOutSize, MM_PDATA_OUT );

   // Prepare the next cycle : it will be automatically started
   // by the "Cycle Start Ready" interrupt
   (void)ibsCyclePrepare( m_master );
...

// The end cycle
void CycleEndCallBack()
{
...
   status = ibsStatusGet( m_master );
   if ( !(status & IBS_DIAG_STATUS_DCRESULT) )
   {
      // Read the input on the MPM
      ibsDataRead( m_master, pdIn, pdInSize, MM_PDATA_IN );
   }
   else
   {
      unsigned short param = ibsParamGet( m_master );
      // TODO - "Erroneous bus cycle : %04x %04x", status, param );
   }
...
}

void MsgRecvCallBack()
{
...
   if ( -1 != ibsReceiveMsg( m_master, (IBSMSG*)m_rcvBuf ) )
   {
      // TODO
   }
...
}

// The user space "Isr" Handler (a thread in my case)
...
void body()
{
   while ( QUIT != m_state )
   {
      int flag = IBS_ISR_MSG_RCV_FLAG |
                 IBS_ISR_CYCLE_END_FLAG;
      int timeout = 5; // TODO - 5ms to be define
      int result = 0;
      result = ibsIsrHandler( m_ibs->m_master, flag, timeout );
      if ( result & IBS_ISR_MSG_RCV_FLAG )
      {
         ibsIsrAck(m_ibs->m_master, IBS_ISR_MSG_RCV_FLAG);
         // TODO - MsgRecvCallBack();
      }
      if ( result & IBS_ISR_CYCLE_END_FLAG )
      {
         ibsIsrAck(m_ibs->m_master, IBS_ISR_CYCLE_END_FLAG);
         // TODO - CycleEndCallBack();
      }
   }
}

----------------------------------------------------------------

For your information, the driver, with a few modifcations, is currently testing on machines.
I'll try to find time to commit changes. I would like to package it with DKMS and properly integrate it on the system.

Although not having much time to devote to the subject, I am very interested by feedbacks, users of this bus are hard to find.

I hope this will be helpful for you.

Good luck.

Pierre

Revision history for this message
Claude LARIVIERE (larivcl) said :
#2

Hello Pierre,

Thank you for your help, I manage to make the following tests :

ibsMasterOpen(), ibsMasterReset(), IBS_Alarm_Stop,
IBS_Confirm_Diagnostics, 0x710 IBS_Create_Configration,
0x301 IBS_Read_Configuration, IBS_Start_Data_Transfer, ibsCyclePrepare,
after that, the status is 0x00E0, bus is running.
In the configuration, I can read that my absolute K3 encoder is present.
I call ibsCyclePrepare every 25ms (or 5ms) and receive a ibsIsrHandler
result with IBS_ISR_CYCLE_END_FLAG set.
-> result = ibsIsrHandler(ibsMaster, flag, timeout ); // 5ms timeout

The ibsDataRead() fuction returns the correct number of bytes read (4),
but the values in the buffer are only 0, the encoder position isn't 0.
I'm not sure of the offset value to pass to this function. In the
configuration returned by IBS_Read_Configuration request, the offset is 0.
-> countRead = ibsDataRead(ibsMaster, (char *) buffer, count, offset)

On the pci device, the green led is ON, on the encoder leds are Ok.

I'm a bit confused, everything seems to work, but the actual data are
not read.

Regards

Le 24/05/2013 22:51, Pierre Quelin a écrit :
> Your question #229563 on ibsdrv changed:
> https://answers.launchpad.net/ibsdrv/+question/229563
>
> Status: Open => Answered
>
> Pierre Quelin proposed the following answer:
> Hello Claude,
>
> thank you for your interest concerning my piece of code.
> I developed this driver on my free time to demonstrate the feasibility of porting VxWorks 5.4/6.3 -> Linux (Xenomai).
> My intention was to limit the kernel side for reliability and to provide a minimum user library with a generic code.
> Unfortunately I do not have a practical example to show you, the application layer is the property of my company. I know that it's not easy, but interbus is not an easy bus and the documentation is not very clear.
>
> Here is a summary of what the application need to do, the cycles are
> generated every 5 ms by a thread which differs from the "standard"
> Phoenix use.
>
> ----------------------------------------------------------------
> main()
> {
> ...
> IBSMASTER m_master;
>
> // Open the device
> m_master = ibsMasterOpen( "/dev/ibs0" );
>
> // ibsMasterReset( m_master );
>
> // TODO - start a cycle, wait the cycle end, ???
>
> ibsMasterClose( m_master );
> ...
>
> }
>
> // To obtain diagnostic information
> ...
> // Check the master
> unsigned short status = ibsStatusGet( m_master );
>
> if ( status != ( IBS_DIAG_STATUS_READY | IBS_DIAG_STATUS_ACTIVE | IBS_DIAG_STATUS_RUN ) )
> {
> unsigned short param = ibsParamGet( m_master );
> // TODO - "Cycle diagnostic : %04x %04x", status, param );
> }
>
> ...
>
> // Start a cycle
> ...
> // Copy the output process data to the MPM
> ibsDataWrite( m_master, pdOut, pdOutSize, MM_PDATA_OUT );
>
> // Prepare the next cycle : it will be automatically started
> // by the "Cycle Start Ready" interrupt
> (void)ibsCyclePrepare( m_master );
> ...
>
> // The end cycle
> void CycleEndCallBack()
> {
> ...
> status = ibsStatusGet( m_master );
> if ( !(status & IBS_DIAG_STATUS_DCRESULT) )
> {
> // Read the input on the MPM
> ibsDataRead( m_master, pdIn, pdInSize, MM_PDATA_IN );
> }
> else
> {
> unsigned short param = ibsParamGet( m_master );
> // TODO - "Erroneous bus cycle : %04x %04x", status, param );
> }
> ...
> }
>
> void MsgRecvCallBack()
> {
> ...
> if ( -1 != ibsReceiveMsg( m_master, (IBSMSG*)m_rcvBuf ) )
> {
> // TODO
> }
> ...
> }
>
> // The user space "Isr" Handler (a thread in my case)
> ...
> void body()
> {
> while ( QUIT != m_state )
> {
> int flag = IBS_ISR_MSG_RCV_FLAG |
> IBS_ISR_CYCLE_END_FLAG;
> int timeout = 5; // TODO - 5ms to be define
> int result = 0;
> result = ibsIsrHandler( m_ibs->m_master, flag, timeout );
> if ( result & IBS_ISR_MSG_RCV_FLAG )
> {
> ibsIsrAck(m_ibs->m_master, IBS_ISR_MSG_RCV_FLAG);
> // TODO - MsgRecvCallBack();
> }
> if ( result & IBS_ISR_CYCLE_END_FLAG )
> {
> ibsIsrAck(m_ibs->m_master, IBS_ISR_CYCLE_END_FLAG);
> // TODO - CycleEndCallBack();
> }
> }
> }
>
> ----------------------------------------------------------------
>
> For your information, the driver, with a few modifcations, is currently testing on machines.
> I'll try to find time to commit changes. I would like to package it with DKMS and properly integrate it on the system.
>
> Although not having much time to devote to the subject, I am very
> interested by feedbacks, users of this bus are hard to find.
>
> I hope this will be helpful for you.
>
> Good luck.
>
> Pierre
>

Revision history for this message
Pierre Quelin (pierre.quelin) said :
#3

Great job,

I think now you need to configure the process data area with the Msg API. I'm not very familiar with this part of interbus because I don't have all the documentation in my possession. I think that you need to configure and map the IO to the bus at first before starting the cycle.
If you have an existing Windows software, I think that it's easy to find this part (not to understand ;-).

In my case :

enum PDataArea
{
   MM_PDATA_OUT = 0x0000, /* process output data */
   MM_PDATA_IN = 0x1000, /* process input data */
};

/* The API to use */
ibsSendMsg( m_ibs, (IBSMSG*)sndBuf, 2000 )
ibsReceiveMsg( m_ibs, (IBSMSG*)rcvBuf )

/* All interbus services */
/* Services for Parameterizing the Controller Board */
IBS_Control_Parameterization = 0x030E,
IBS_Set_Indication = 0x0152,
IBS_Set_Value = 0x0750,
IBS_Read_Value = 0x0351,
IBS_Initiate_Load_Configuration = 0x0306,
IBS_Load_Configuration = 0x0307,
IBS_Terminate_Load_Configuration = 0x0308,
IBS_Activate_Configuration = 0x0711,
IBS_Deactivate_Configuration = 0x0712,
IBS_Confirm_Diagnostics = 0x0760,

/* Services for Defining Process Data Description */
IBS_Initiate_Put_Process_Data_Description_List = 0x0320,
IBS_Put_Process_Data_Description_List = 0x0321,
IBS_Terminate_Put_Process_Data_Description_List = 0x0322,

/* Services for assigning Process Data */
IBS_Initiate_Load_Process_Data_Reference_List = 0x0324,
IBS_Load_Process_Data_Reference_List = 0x0325,
IBS_Terminate_Load_Process_Data_Reference_List = 0x0326,

/* Services for Direct INTERBUS Access */
IBS_Start_Data_Transfer = 0x0701,
IBS_Alarm_Stop = 0x1303,
IBS_Stop_Data_Transfer = 0x0702,

/* Diagnostic Services */
IBS_Get_Error_Info = 0x0316,
IBS_Get_Version_Info = 0x032A,
IBS_Get_Diag_Info = 0x032B,
IBS_Control_Statistics = 0x030F,

/* Automatic Indications of the Controller Board */
IBS_Fault = 0x0341,
IBS_Device_Fail = 0x1340,
IBS_Bus_Error = 0x2342,

/* PCP */
IBS_Load_CRL_Attribute_Loc = 0x0264,
IBS_PCP_Read = 0x0081,
IBS_PCP_Write = 0x0082,
IBS_PCP_Status = 0x0086,
IBS_PCP_Initiate = 0x008B,
IBS_PCP_Abort = 0x088D,

Good luck

Pierre

Revision history for this message
Pierre Quelin (pierre.quelin) said :
#4

In addition :

A bug in the user lib with the IBSMSG body size
...
typedef struct
{
   unsigned short id;
   unsigned short nb;
   unsigned short body[254]; /* 512/sizeof(unsigned short) - 2 */
} IBSMSG;
...

Pierre

Revision history for this message
Claude LARIVIERE (larivcl) said :
#5

Hello Pierre,

Everything works very well now !

I use the MM_PDATA_IN address at 0x1000 :
countRead = ibsDataRead(ibsMaster, (char *) buffer, count, MM_PDATA_IN +
offset);

I have to test with a larger configuration (50 absolute encoders + I/O
modules) and I plan to use the real-time sheduler to reduce threads
latencies.
Do you know an easy way to load the driver at system boot ? (I'm not a
Linux expert)
If you need help to test or want feedbacks...

Thank you for this great job and for your rapid replies !

Claude

Revision history for this message
Pierre Quelin (pierre.quelin) said :
#6

Congratulations!

Thank you very much for your feedback. We are now two people in the world using this type of fieldbus ;-)

About loading the driver at startup, I use a method that is not very clean. I manage the loading of the driver as the start of a service.

I create a file like this /etc/init.d/myservice

#==========================================================
#!/bin/sh

# Handle manual control parameters like start, stop, status, restart, etc.

case "$1" in
  start)
    # Start daemons.

    echo -n $"Starting <myservice>: "
    echo
    /home/MyHome/ibsdrv/load
    echo
    ;;

  stop)
    # Stop daemons.
    echo -n $"Stoping <myservice>: "
    /home/MyHome/ibsdrv/unload
    echo

    # Do clean-up works here like removing pid files from /var/run, etc.
    ;;
  status)
    status <myservice>

    ;;
  restart)
    $0 stop
    $0 start
    ;;

  *)
    echo $"Usage: $0 {start|stop|status|restart}"
    exit 1
esac

exit 0
#==========================================================

The "normal" way is to add the module with the kernel lib and add the module in /etc/module.

As I say before, I would like to package it with DKMS and properly integrate it on the system. I do not know if I would find the time to do something clean.

In all case, all feedbacks are welcome.

Thank you very much

Pierre

Can you help with this problem?

Provide an answer of your own, or ask Claude LARIVIERE for more information if necessary.

To post a message you must log in.