Difference between revisions of "HMS anybus Linux"

From ArmadeusWiki
Jump to: navigation, search
(Creation of the FPGA design with POD)
(Creation of the FPGA design with POD)
 
(One intermediate revision by the same user not shown)
Line 34: Line 34:
  
 
<pre class="host">
 
<pre class="host">
   $ make linux26-menuconfig
+
   $ make linux-menuconfig
 
</pre>
 
</pre>
  
Line 54: Line 54:
 
In your Armadeus directory, select the HMS Anybus linux driver anybus_interface:
 
In your Armadeus directory, select the HMS Anybus linux driver anybus_interface:
 
<pre class="host">
 
<pre class="host">
   $ make linux26-menuconfig
+
   $ make linux-menuconfig
 
</pre>
 
</pre>
  

Latest revision as of 13:30, 7 February 2013

  • 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

Anybus interface design FPGA

  • The FPGA design is available in firmware/pod_scripts/apf51_anybus_interface.bin
  • This design and the drivers must be generated by the POD script in your ARMadeus directory:
firmware/pod_scripts/apf51_anybus_interface.pod

don't forget to uncomment the selectprojecttree command value in this file, and replace the string «your_armadeus_directory» by your armadeus directory absolute complete path (avoid ~).

selectprojecttree your_armadeus_directory/target/linux/modules/fpga/POD
driver.selectprojecttree your_armadeus_directory/target/linux/modules/fpga/POD
driver.copydrivers
Warning Warning: We have some trouble with IRQs and GPIOs, if you have to change GPIO or IRQ number, check the two command "setgeneric" in the script apf51_anybus_interface.pod .
  • The GPIO reset number is the first number displayed when you do :
  # modprobe pod_gpio
  # modprobe pod_gpio_platform
  • The IRQ number can be obtained by add 1 to the last number when you do :
  # modprobe irq_ocore
  # modprobe pod_irq_mng


  • Then, enable Drivers generated by POD and disable Drivers for wishbone example
  $ make linux-menuconfig
Device Drivers  --->
    [*] Support for specific Armadeus drivers  --->
        [*]   FPGA specific drivers and tools  --->
            [*]   Board drivers generated by POD
						[...]
            <M>     POD irq
            <M>     pod_gpio_platform
            <M>     POD anybus interface driver
            [ ]   Board designs

anybus_interface Linux driver installation

Kernel configuration

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

  $ make linux-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 protocol.
    • 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);

Example

  • Have a look to the source code anybus_tools in your armadeus directory, target/package/anybus_tools/

Links