HMS anybus Linux

From ArmadeusWiki
Revision as of 17:45, 27 July 2011 by KevinJ (Talk | contribs)

Jump to: navigation, search
Page under construction... 

Construction.png Informations on this page are not guaranteed !!

  • The Anybus module allows the Armadeus board to communicate on 18 differents industrial network such as Profibus, Modbus-TCP/RTU, CANOpen, ...
  • The following instructions is relative to Armadeus boards APF51-Dev and APF51 with FPGA. Please ensure you use the trunk version of Armadeus.

Creation of the FPGA design with POD

TODO

anybus_interface Linux driver installation

Kernel configuration

In your Armadeus directory, select the HMS Anybus linux driver anybus_interface:

  $ make linux26-menuconfig
Device Drivers  --->
  [*] Network device support  --->
    <M>   HMS Anybus driver

Loading the modules driver

  • Load the driver generated by POD.
 # modprobe pod_anybus_interface_platform
  • Load the kernel driver.
 # modprobe anybus_interface
  • Check if the interface anybus0 is available.
 # ifconfig anybus0
 anybus0   Link encap:UNSPEC  HWaddr 00-45-02-10-A0-0A-33-C7-00-00-00-00-00-00-00-00  
          NOARP  MTU:520  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:10 
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)
          Interrupt:83 


  • Mount the interface.
 # ifconfig anybus0 up

Check the surface mounted LED on the Anybus module (not the front LEDs). This LED should blink at 1Hz if the module is initialised, and 2Hz if not. Then, you can use the interface.

anybus-tools

Description

anybus-tools is a set of tools used to communicate with your HMS Anybus module through the anybus_interface Linux driver.

Installation on your target

  • In your Armadeus directory on your host:
 $ make menuconfig
  • Choose anybus-tools
Package Selection for the target  --->
  Armadeus specific tools/utilities  --->
    [*] anybus-tools

Then, reflash your rootfs.

Usage

  • In the APF environnement
 # anybus-tools
  • The first window ask you which anybus interface you want to use (anybus0 by default).

Features

Edit input area

  • Move in the HMS Anybus input area memory with arrow keys and edit a field hitting the < Enter > key.

Edit input area memory

Map output area

  • Move in the HMS Anybus output area memory with arrow keys to watch messages received by the module.

Mailbox message

  • Send and receive mailbox messages.

Mailbox interface

Read register

  • Read a specific register in the HMS Anybus module memory.

Change interface

  • Choose a different anybus interface.

About...

  • Show "About..." dialog.

Help

  • Display some help ...

Programmation

The anybus_interface driver is accessible by a short C program (as a classic network interface). However, some informations and options need to be set. Please include net/anybus_interface.h

Initialization

  • Declare some structures and variable
    • Structure ifreq will be used to do network interface request
    • Structure sockaddr_ll is a socket descriptor.
    • int sk is the socket id.
struct ifreq ifr;
struct sockaddr_ll addr;
int sock = 0;
  • Initialize some fields
    • The anybus_interface driver use AF_PACKET family with the non-connected protocole.
    • Put the interface name in the ifreq structure.
addr.sll_family = AF_PACKET;
addr.sll_protocol = IPPROTO_UDP;
addr.sll_pkttype = PACKET_BROADCAST;

strncpy(ifr.ifr_name, "anybus0", strlen("anybus0"));
  • Create the socket
if ((sock = socket(PF_PACKET , SOCK_RAW, AF_PACKET)) < 0 ) {
    perror("socket");
    return sock;
}
  • And associate it with the anybus network interface
ioctl(sock, SIOCGIFINDEX, &ifr);
addr.sll_ifindex = ifr.ifr_ifindex;
  • Bind the descriptor to the socket
if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
    perror("bind");
    return EXIT_FAILURE;
}

Communication (send/recv)

  • First, you have to declare an anybus_frame structure
struct anybus_frame frame;
  • This structure contain 3 fields :
    • .reg : offset register of the anybus input/output memory.
    • .len : Length of the data in this frame. The max len is given by ANYBUS_DATA_LEN.
    • .data[n] : value at the address offset + n.
  • Initialize and send the frame on the fieldbus
    • The following code will write the 16bits words 0x1234 and 0x9876 in the HMS Anybus input memory at the address 0x12 and 0x14 (16bits access)
frame.reg = 0x12;
frame.len = 2;
frame.data[0] = 0x1234;
frame.data[1] = 0x9876;

if ((ret = send(sock, (void *)&frame, sizeof(frame), 0)) < 0) {
    perror("send");
    return ret;
}
  • Receive a frame on the fieldbus
    • The following code will receive the values read in the HMS Anybus Output memory. The frame.reg will be always 0 and .len will be always 256.
    • The recv() function is blocking until the HMS Anybus Output memory is changed.
if((ret = recv(sock, (void *)&frame, sizeof(frame), 0)) < 0) {
    perror("recv");
    return ret;
}

ioctl

  • Anybus ioctls are independent of the socket id. The driver implement a char device /dev/anybusX_device.
  • Five ioctls commands are available.
  • The structure given to the ioctl commands is:
struct mailbox_msg {
	unsigned short id;
	unsigned short msg_information;
	unsigned short command_number;
	unsigned short data_size;
	unsigned short extended_word[8];
	unsigned short data[ANYBUS_DATA_LEN];
};

or

struct anybus_register {
	unsigned short address;
	unsigned short value;
};

Mailbox read

  • Initialize a mailbox_msg structure and a file id.
  • Open the device's file.
  • Do the ioctl command ANYBUS_MB_READ.
  • close the device file.
struct mailbox_msg received_mail;
int fd_device;

fd_device = open("/dev/anybus0_interface", O_RDONLY);

if((ret = ioctl(fd_device, ANYBUS_MB_READ, &received_mail)) < 0) {
    perror("ioctl");
    return ret;
}

/* The fields of the received_mail structure contains now the informations about 
the last mailbox message emitted by the HMS Anybus module. */

close(fd_device);
Note Note: It is possible to do a select() command on the device file /dev/anybusX_device.


Mailbox write

  • Initialize a mailbox_msg structure.
  • Open the anybus device file.
  • Fill the mail_to_send structure fields.
  • Do the ioctl command ANYBUS_MB_READ.
  • close the device file.
struct mailbox_msg mail_to_send;
int fd_device;

fd_device = open("/dev/anybus0_interface", O_RDONLY);

/* Fill the mail_to_send structure fields here */

if((ret = ioctl(fd_device, ANYBUS_MB_WRITE, &mail_to_send)) < 0) {
    perror("ioctl");
    return ret;
}

close(fd_device);

Map input area

  • Declare a structure anybus_frame.
  • Open the device file.
  • Do the ioctl command ANYBUS_MAP_INPUT.
  • Close the device file.
struct anybus_frame frame;
int fd_device;

fd_device = open("/dev/anybus0_interface", O_RDONLY);

if ((ret = ioctl(fd_device, ANYBUS_MAP_INPUT, frame.data)) < 0) {
    perror("ioctl");
    return ret;
}

/* The frame.data field has been filled */

close(fd_device);

Map output area

  • Declare a structure anybus_frame.
  • Open the device file.
  • Do the ioctl command ANYBUS_MAP_OUTPUT.
  • Close the device file.
struct anybus_frame frame;
int fd_device;

fd_device = open("/dev/anybus0_interface", O_RDONLY);

if ((ret = ioctl(fd_device, ANYBUS_MAP_OUTPUT, frame.data)) < 0)
    return ret;

/* The frame.data field has been filled */

close(fd_device);

Read anybus register

  • Declare a structure anybus_frame.
  • Open the device file.
  • Give the address register (here 0x7D5)
  • Do the ioctl command ANYBUS_MAP_OUTPUT.
  • Close the device file.
struct anybus_register anybus_reg
int fd_device;

fd_device = open("/dev/anybus0_interface", O_RDONLY);

anybus_reg.address = 0x7D5;

if ((ret = ioctl(fd_device, ANYBUS_READ_REG, &anybus_reg)) < 0) {
                return ret;
            }

/* The anybus_reg.value field has been filled */

close(fd_device);

closing the socket

close(sock);

Links