Sie sind auf Seite 1von 56

Project

6th semester - SS2006


May 26, 2006

HOWTO: NIOS-CPU with additional hardware driven with Clinux

Caretaker: Prof. Dr.-Ing. M. Strahnen Peter Feuerer Steffen Gutmann Sascha Haensch Ronny Schroeder
SID: 36635 SID: 36614 SID: 34447 SID: 36607

Hochschule Ulm
Prittwitzstrasse 10 89075 Ulm

NIOS-CPU with additional hardware driven with Clinux

Contents

Contents
1 Introduction 1.1 1.2 1.3 Conceptual Formulation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Disambiguation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Used Environment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.3.1 1.3.2 2 Used Hardware . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Used Software . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2 2 2 3 3 5 6 6 8 8 8 11 27 27 27 27 27 28 28 30 31 32 34 34 34 34 34 36 36 36 37 37

Course Of Action 2.1 Necessary Preparations and Rough Flow Chart . . . . . . . . . . . . . . . . . . . . .

Creating own Hardware 3.1 3.2 3.3 Conception . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Creating VHDL Specication . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Add custom hardware to the NIOS II processor . . . . . . . . . . . . . . . . . . . . .

Installing Clinux toolchain 4.1 Building the embedded Clinux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1.1 4.1.2 4.1.3 4.1.4 4.1.5 4.1.6 4.2 4.3 Clinux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

setup the development system . . . . . . . . . . . . . . . . . . . . . . . . . . adding a user . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Download sources of microtronixs nios2 linux . . . . . . . . . . . . . . . . . Building the nios2 linux . . . . . . . . . . . . . . . . . . . . . . . . . . . . . set the path variable . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

conguring and compiling the kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . Ready to start . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Programming kernel driver 5.1 Implementation of the driver . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1.1 5.1.2 5.1.3 5.2 5.3 5.4 General . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Denes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Function calls . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Adding device les to rootfs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Adding driver to kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Building the kernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

User-space programs 6.1 General . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 1

NIOS-CPU with additional hardware driven with Clinux

Contents

6.2 7

Using custom IO . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

37 38 38 38 38 39 40 41 42 46 52 52 52 52 53 54

Using preinstalled VM 7.1 7.2 7.3 7.4 Linux host system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Windows host system . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Usage . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . Moving data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

8 9

Summary Addendum

A VHDL Code B Kernel module code C The Expansion Board C.1 Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C.2 Bill Of Materials . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C.3 Connection between Expansion Board and Nios II Evaluation Kit . . . . . . . . . . . . C.4 Schematic . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . C.5 PCB-Layout . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 2

NIOS-CPU with additional hardware driven with Clinux

Introduction

1
1.1

Introduction
Conceptual Formulation

During the 6th semester of our studies in computer engineering at university of applied sciences Ulm we had to process a project which practiced us how software and hardware project are realized. Our order was to expand a FPGA based Microcontroller and get Clinux running on it. The nal goal was to write a howto which describes the following tasks: Add a simple parallel I/O-device to the Nios II processor Customize Clinux to the modied processor Write a driver to control the I/O-device Other people should be able to add their own VHDL specied hardware devices to a Nios II processor after reading this document. They also should be able to write a device driver which acts in the kernel space and can be accessed from the user space. Because we want to prevent the readers from running into the same traps as we did we also describes some problematic parts.

1.2

Disambiguation

In this howto we use some technical terms to describe the development process. Maybe not all of them are well known so we explain the most important of them. FPGA A Field Programmable Gate Array (FPGA) is a semiconductor device containing programmable logic components and programmable interconnects. The programmable logic components can be programmed to duplicate the functionality of basic logic gates such as AND, OR, XOR, NOT or more complex combinatorial functions such as decoders or simple math functions. In most FPGAs, these programmable logic components also include memory elements, which may be simple ip-ops or more complete blocks of memories. Nios II The Nios II is a soft-core embedded processor manufactured by Altera. Soft-core means that FPGA developers can choose from a myriad of system congurations, picking the best-t CPU core as well as selecting processor peripherals. There are three Nios II CPU cores: Nios II/f (fast), Nios II/e (economy) and Nios II/s (standard). Avalon Bus The Avalon Bus is the internal bus system of a Nios II processor. The subcomponents of a Nios II processor use it to communicate with each other. User specied hardware can be integrated into a Nios II processor by using this bus. Clinux Clinux (which stands for MicroControllerLinux) is a Linux kernel fork for microcontrollers without a memory management unit (MMU). It is based on version 2.6 of the Linux kernel.
Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 3

NIOS-CPU with additional hardware driven with Clinux

Introduction

VHDL VHDL (Very High Speed Integrated Circuit Hardware Description Language) is a hardware description language used to design and specify complex digital systems. In our case we use VHDL to describe same additional hardware for the Nios II processor.

1.3

Used Environment

In this section we describe which hardware and software we used for this project. Due to the fact that software become obsolete very fast there may be newer versions available. Anyway the basic principles should be transferable. 1.3.1 Used Hardware

The Nios II Evaluation Kit There were two Nios II Evaluation Kits from Altera at our disposal. The most important features are: a CycloneTM EP1C12F324 FPGA 16 Mbytes of external SDRAM 8 Mbytes of external ash a RJ-45 connector and 10/100 Ethernet physical layer component a USB connector, providing power and host communication a Prototype area for user I/O user-dened push-button switches user-dened LEDs some further periphery

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 4

NIOS-CPU with additional hardware driven with Clinux

Introduction

Figure 1: The Nios II Evaluation Kit The expansion Board We designed and build a simple simulation board for our IO-port. Every IO-pin can be connected either with a button or with a LED. Figure 2 shows the principle for one IO-pin.

Figure 2: The expansion board The button or the LED can be selected with a jumper. Jumper on position 1 means that the IO-pin must act as an input and the button is used. Jumper on position 2 means that the IO-pin must act as an output and the LED is used. You can nd the whole schematic and the layout in appendix C.
Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 5

NIOS-CPU with additional hardware driven with Clinux

Introduction

Attention: There is no automatically detection if a pin is used as output or input. The user has to take care about this. Wrong settings could lead to the damage of one or both boards! 1.3.2 Used Software

Quartus II Web Edition Quartus II is a software made by Altera. With this software you can create HDL based hardware designs, simulate them, assign the pins of a FPGA and create a netlist which is used to congure a FPGA. The Web Edition is free available and comes with the Nios II Evaluation Kit. SOPC Builder The SOPC Builder is part of the Quartus II software. It is used to create or customize a Nios II processor.

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 6

NIOS-CPU with additional hardware driven with Clinux

Course Of Action

2
2.1

Course Of Action
Necessary Preparations and Rough Flow Chart

We advise to constitute two teams - one for the hardware part and on for the software part. The hardware team can start like this: Get familiar with VHDL Install Quartus II Web Edition Get familiar with Quartus (Elektor Howto - [7]) Create own device with VHDL Add own device to Nios II processor with SOPC Builder Align the Quartus project Compile the new Nios II processor

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 7

NIOS-CPU with additional hardware driven with Clinux

Course Of Action

The software team can start like this: Get familiar with linux kernel programming Install Clinux toolchain Create kernel module

Then both teams can nish the project: Build Clinux Cong the FPGA Program Clinux image to the processor Have fun and enjoy your life ;)

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 8

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

3
3.1

Creating own Hardware


Conception

In the rst place it is important to feel condent about how the new hardware device should work. In our case we have two 8-Bit registers. One register contains the data which comes from respectively goes to the Nios II processor. The other register is the direction select register. It denes if a pin is used as input or output. So we need two addresses (at least one address line) and a 8-Bit data line to the processor. We want to keep this example simple so we decided that this device should became a slave device. We do not use any interrupts. Reading data from the input have to be done by polling the data register. Figure 3 shows a draft of our device.

Figure 3: Draft of the 8-Bit IO device

3.2

Creating VHDL Specication

First we have to specify which signals we need for our device and which of them are connected with the Avalon bus. In the description of the Avalon bus had to nd out which signals are necessary. In our case we need the following signals: address: Internal address offset.* chipselect: Signal to activate our device.* clk: Synchronization clock for the Avalon slave interface. All signals are synchronous to clk.*
Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 9

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

reset n: Resets our device. Actually the developer decides what happen in this case.* write n: Indicates a write cycle.* read n: Indicates a read cycle.* writedata: Data lines for write transfers.* out port: Data lines which connects our device with the IO-pins. readdata: Data lines for read transfers.* * These signals are required by the Avalon bus. Please note: The signal readdata is also specied as output because output means not connected with the hardware pins of the FPGA but data are sent via this line(s) to any other component outside the component which is specied here! As a result we got these entity which denes the interface of our device. entity pio eigen is port ( inputs: signal address : IN STD LOGIC VECTOR (1 DOWNTO 0); signal chipselect : IN STD LOGIC; signal clk : IN STD LOGIC; signal reset n : IN STD LOGIC; signal write n : IN STD LOGIC; signal read n : IN STD LOGIC; signal writedata : IN STD LOGIC VECTOR (7 DOWNTO 0); outputs: signal out port : INOUT STD LOGIC VECTOR (7 DOWNTO 0); signal readdata : OUT STD LOGIC VECTOR (7 DOWNTO 0) ); end entity pio eigen; We are geared to the existing VHDL examples and so we two address lines which gives us four addresses although we need only two of them. Now we have to dene the architecture which describes the behavior of our device. Within the architecture we use local signals. The actual functionality is described within a process. The process is sensitive for the clock signal and for all asynchronous signals.

10

process (clk, reset_n)

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 10

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

First we check if reset n gets a 0 signal. In that case we set both registers (data out, dir reg) to 0.

if reset_n = 0 then -- clear the output register and the direction register data_out <= std_logic_vector("00000000"); dir_reg <= std_logic_vector("00000000");

Then we check if a rising edge occurs. A rising edge detects a read or write transfer.

elsif clkevent and clk = 1 then

Now we have to check if our device is responded (chipselect = 1), if its a read or write transfer (read n = 0 or write n = 0) and if data out or dir reg is meant (we decided to assign the address 00 to data out and 01 to dir reg). The following (a little complex) statement checks if we want to write to data out.

if std_logic(((chipselect AND NOT write_n) AND to_std_logic((((std_logic_vector ("000000000000000000000000000000") & (address)) = std_logic_vector ("00000000000000000000000000000000")))))) = 1 then

The statement checks if chipselect is 1 and if write n is 0. The Avalon bus has a 32 Bit address bus so this statement adds the two Bit internal address offset to 30 zeros and compares it with 32 zeros. The result of these comparison is converted into a boolean value (with to std logic). This value is compared with 1. If all three conditions are true a write transfer to data out is detected. The other three types of transfers (read from data out, read from dir reg and write to dir reg) works similarly. The rest of the code relates to the functionality of the parallel IO-port. Look at the complete well documented source code in our appendix A to nd out how it works. Attention: The name of the entity and of the VHDL le have to be the same (In our case pio eigen.vhd). The name of the architecture must be europa. We got a lot of problems if we do not follow this. The syntax check of Quartus also did not work very well. If you have the same problems use the open source VHDL simulator GHDL for Linux (command line: ghdl -s nameofle.vhd).

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 11

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

3.3

Add custom hardware to the NIOS II processor

In this chapter we show the needed steps to create a new project and include the specied component from the last section. 1. First we need a blank project based on the standard design supported by Altera. Create a copy of the standard project directory C:\altera\kits\nios2 51\example\vhdl\ niosII cyclone 1c12 eval\standard and put it to C:\ 2. Now it is important to set user rights for the new directory. Therefore type the following listing in a NIOSII SDK Shell. cd C: ; chmod -R 777 standard

Figure 4: 3. Now copy the new entity pio eigen.vhd into the project directory c:\standard\ 4. Launch Quartus and open the project le c:\standard\standard eval board.qpf 5. Open the SOPC Builder with a double click on the standard 1c12 symbol

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 12

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

6. Click on create new component

Figure 5: Clipping of the SOPC Builder

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 13

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

7. The Component Editor opens. Click on the second tab "HDL Files"

Figure 6: Component Editor - HDL Files Here add the les of the used library altera vhdl support.vhd and the specication of our entity pio eigen.vhd. Click on the button Add HDL File ... to get a File open dialog.

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 14

NIOS-CPU with additional hardware driven with Clinux 8. Select the two les and click on Offnen to add the les

Creating own Hardware

Figure 7: File open dialog

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 15

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

9. The added les will be checked (visualized by a green blinking background)

Figure 8: Syntax check 10. If everything works ne, the message Component "pio eigen" is ok should appear in the status area

Figure 9: OK message

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 16

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

11. Click on the next tab called "Signals" an verify all signals

Figure 10: Component Editor - Signals

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 17

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

12. Jump to the last tab "Component Wizard"

Figure 11: Component Editor - Component Wizard Click the Finish... button and submit the message "do you wish to save" with yes

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 18

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

13. Look at the foorbar group an double click on the component pio eigen

Figure 12: Quartus - Add component Change nothing in the upcomming dialog called Settings, click only Finish

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 19

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

14. Now the new component should appear in the integrities list of the NIOS chip

Figure 13: Quartus - Integrities list Click the button Generate

Figure 14: Dialog - Integrities list To close this dialog click on Exit

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 20

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

15. Back in Quartus a dialog asks you, if you want to update the NIOS symbol. Click on yes and in the next window click all symbols or blocks in file 16. Be carefull! In Quartus 5.x the wires between different symbols are not automatically connected to the correct outputs.

Figure 15: Quartus - missmatched signals 17. Connect all symbols like shown in gure 16

Figure 16: Quartus - correct connected signals

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 21

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

18. Click on the symbol button in the toolbox. In the dialog select a bidir pin out of the library primitives

Figure 17: Quartus - add bidirectional output 19. To connect the new symbol place it right next to the output "out port to and from the pio eigen[7..0]" and draw a connecting wire between them

Figure 18: Quartus - connect output

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 22

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

20. Double click on the just created symbol to open the Pin Properties dialog Enter "pio io[8..1]" into eld Pin name(s) and click OK

Figure 19: Quartus - Pin properties 21. Save your work by selecting Save from the File menu

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 23

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

22. Click Processing Start Start Analysis & Elaboration to add your new pio io pins to the pin list

Figure 20: Quartus - Start Analysis & Elaboration 23. Click Assignment Pins

Figure 21: Quartus - Pin assignment

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 24

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

24. Scroll down to the lower end of the pin list. Click on the <<new>> eld in the rst column an choose "pio io[1]"

Figure 22: Quartus - new assignment - pin Click on the <<new>> eld in the second column an choose "PIN L13"

Figure 23: Quartus - new assignment - location Repeat this to assign all 8 pins. pio io pin 1 PIN L13 2 PIN N14 3 PIN L14 4 PIN M15 5 PIN T17 6 PIN R17 7 PIN M13 8 PIN P14

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 25

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

25. Again save your work by selecting Save from the File menu 26. Click Start compilation

Figure 24: Quartus - Compile Now is the time to get a cup of coffee, this process might take about 45min. We suggest to open the Windows Task Manager to verify all the time, that Quartus does its work, cause it crashed (not responding = 0% cpu) sometimes. 27. After the compilation ended sucessfully, click on Programmer

Figure 25: Quartus - Start Programmer 28. Click "Hardware Setup...". In the upcoming dialog select "Nios II Evaluation Board [USB-0]" and click the close button.

Figure 26: Programmer - Select device

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 26

NIOS-CPU with additional hardware driven with Clinux

Creating own Hardware

29. Check the box in the column "Program/Configure" and press Start

Figure 27: Programmer - Programm the board 30. Dontt click Cancel in the upcoming dialog (if you do so, the hardware isnt running on the board)

Figure 28: Programmer - OpenCore Plus Status Now the hardware is loaded into SRAM and a linux image can be downloaded to and ran on the board: 31. Open a NiosII SDK Shell and enter: nios2-download -g zImage ; nios2-terminal You can get a prepacked zImage from the CD which comes with this tutorial. Or you can create one by yourself. (described in section 4)

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 27

NIOS-CPU with additional hardware driven with Clinux

Installing Clinux toolchain

4
4.1

Installing Clinux toolchain


Building the embedded Clinux

4.1.1 Clinux As in the system architecture document described the Nios II board comes by default with an preinstalled Clinux distribution of microtronix1 . Because the source code of this distribution is not free available we decided to use the nios2 Clinux community solution2 . The hardware we build on the nios2 is not very complex, so our Linux should just be able to work with the nios2 cpu core, sdram, full featured timer, jtag/serial console and the c ash. There is no MMU on the current nios2, so no virtual memory, no shared objs/libs, no fork, and stack size is xed. In the following steps there is described how to build the tools, compile the kernel and build the port applications for this Clinux on a Linux platform. If you get problems during this little tutorial about building the embedded linux, please have a look at the more detailt howto at [9]. For reading it it is necessary that you have been registered. To run into less trouble we recommend to accomplish these steps on a Linux platform. In our case we used our laptops based on the Fedora Core Linux distribution. 4.1.2 setup the development system

At rst we have to build the cross-compiler. We used the gcc3, because the gcc4 cause trouble on binuntils-2.15. By using a Fedora Core Linux the development packages have to be installed and we recommend to update your system by running "yum update" before installing the compat-gcc-32 package (gcc3) su # your root passwd yum install compat-gcc-32 cd /usr/bin mv gcc gcc4 ln -s gcc32 gcc exit 4.1.3 adding a user

To avoid errors it is very useful to execute the following tasks as a separate user e.g jack. In this tutorial we do all operations as the user jack but using other users except the root is also possible. To add a user execute the following command.
1 2

www.microtronix.com http://scorpius.homelinux.org/marc/nios2.html

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 28

NIOS-CPU with additional hardware driven with Clinux

Installing Clinux toolchain

su - # your root passwd useradd jack passwd jack Login as the user you created e.g. jack an check if home directory e.g. /home/jack exists. 4.1.4 Download sources of microtronixs nios2 linux

The microtronix port of the nios2 Linux is available at http://forum.niosforum.com/downloads/1 4/nios2linux-1.4.zip. After downloading this zip-le to /downlaod directory and extracting we get directories containing several contents, Cygwin environment documents and references about Clinux examples about the linux toolbox, busybox, utils etc. linux system, containing the uClib, kernel, le system and basic applications Conguration les 4.1.5 Building the nios2 linux

To build the linux we used a very handy and useful build script available at http://hungryhippo.jot.com/WikiHome/build.zip. Downloaded and extracted to /download we can build a linux. This directory contains a few conguration les the build script needs. By starting the script you can see how the procedure fetches a lot of les, congures an compiles it. cd /download unzip build.zip ./build This could take a couple of minutes depending on the computer you use. The several steps the task executes are Preparing the kernel sources ... unzip -aoq ../nios2linux-1.4.zip ... patch -p0 </download/kernel.diff ...
Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 29

NIOS-CPU with additional hardware driven with Clinux

Installing Clinux toolchain

patch -p1 </download/mx140apps.diff ...

In the main command lines in this section the microtronixs port of Nios II Linux will be extracted an the kernel and applications will be patched. Preparing the Clinux distribution sources ... wget -N http://www.uclinux.org/pub/uClinux/dist/ uClinux-dist-test-20051209.tar.bz2 ... tar jxf /download/uClinux-dist-test-20051209.tar.bz2 ... patch -p0 </download/uClinux-dist.diff ...

The whole Clinux distribution (uClinux-dist-test-20051209.tar.bz2) will be downloaded by wget in this stage, but we advise to download this le before running this build script at http://www.uclinux.org/pub/uClinux/dist/ because of the large le size about 200 MB. After downloading, the archive will be extracted and a needed Clinux patch will be done. Downloading the buildroot snapshot ... SNAPSHOT=20060320 wget -N http://buildroot.uclibc.org/downloads/ snapshots/buildroot-$SNAPSHOT.tar.bz2 wget -N http://www.uclibc.org/downloads/ snapshots/uClibc-$SNAPSHOT.tar.bz2 wget -N http://busybox.net/downloads/ snapshots/busybox-$SNAPSHOT.tar.bz2 ln -s buildroot-$SNAPSHOT.tar.bz2 buildroot-snapshot.tar.bz2 ln -s uClibc-$SNAPSHOT.tar.bz2 uClibc-snapshot.tar.bz2 ln -s busybox-$SNAPSHOT.tar.bz2 busybox-snapshot.tar.bz2 ... tar jxf /download/buildroot-snapshot.tar.bz2 ... ln -s /download dl ...

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 30

NIOS-CPU with additional hardware driven with Clinux

Installing Clinux toolchain

Among the Clinux sources, several other packages are needed to build a full runnable embedded linux. At rst we download the buildrom which is a set of Makeles and patches that allows to generate both a cross-compilation toolchain and a root le system for our target easily . The cross-compilation toolchain uses uClibc which we download in the next step. To let the operator work with the embedded linux, we need a Embedded Linux BusyBox which combines tiny versions of many common UNIX utilities into a single small executable. We get this tools by downloading the busybox. Finally we create some links for these packages for compiling. Patch the conguration and prepare the root le system ... #path the config patch -p0 </download/buildroot.diff make oldconfig make ... # prepare root fs mkdir /rootfs cp -a /buildroot/build_nios2/root/* /rootfs ...

To get working our build root we just need to patch and compile it. Then at last we generate the rootfs directory the kernel needs to build the initramfs image. After a few minutes depending on your machine you use the script will nish successfully. You could have a look at your home directory e.g /home/jack and see several directories. The uClinux distribution will be prepared in /uClinux-dist. Applications ported by microtronix will be in /apps. The kernel we will generate is the 2.6.11-uc0 which you can nd in /linux-1.6.x with zImage, EPCS MTD and avalon watchdog drivers. If you plan to add or remove dev nodes you have to edit the /download/rootfs list le. We will do this in the driver development section later on. For more Information about the build script, please have a look at the complete script in the addendum. 4.1.6 set the path variable

For using the cross compiler gcc we need to use the following path. PATH=$PATH:/buildroot/build_nios2/staging_dir/bin A better solution is to set this path permanently in the /.bash prole. PATH=$PATH:$HOME/bin:$HOME/buildroot/build_nios2/staging_dir/bin
Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 31

NIOS-CPU with additional hardware driven with Clinux

Installing Clinux toolchain

To verify that you set this path correctly run this command, nios2-linux-uclibc-gcc -v if you get an error message you did something wrong. Run this to verify that you have the proper busybox in FLT format, nios2-linux-uclibc-flthdr /rootfs/bin/busybox it is correct if the result displays the FLT header like this, /home/jack/rootfs/bin/busybox Magic: bFLT Rev: 4 Build Date: We Apr 26 11:55:05 2006 Entry: 0x40 Data Start: 0x632c8 Data End: 0x7bb80 BSS End: 0x96750 Stack Size: 0x3e80 Reloc Start: 0x7bb80 Reloc Count: 0x344d Flags: 0x1 ( Load-to-Ram )

4.2

conguring and compiling the kernel

cd /linux-2.6.x # generate nios2_system.h from ptf make ARCH=nios2nommu CROSS_COMPILE=nios2-linux-uclibchwselect SYSPTF=your_system.ptf To compile the linux kernel we have to set a parameter which describes the hardware of your board. It is important that this le matches your current hardware. In our case we use the Altera Cyclone II NIOS standard board with cyclone 1c12 chip. If you create optional hardware like in our case you have to take the ptf le you created with the Altera Development tool. Or you can use the standard ptf le from altera/kits/nios2 51/example/vhdl/niosII cyclone 1c12 eval/standard/standard 1c12.ptf. By running the command line you will be asked what hardware devices you want to use. This could look like the following, --- Please select which CPU you wish to build the kernel against:
Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 32

NIOS-CPU with additional hardware driven with Clinux

Installing Clinux toolchain

(1) cpu - Class: altera_nios2 Type: s Version: 5.11 Selection: 1 --- Please select a device to upload the kernel to: (1) ext_flash Class: altera_avalon_cfi_flash Size: 16777216 bytes Selection: 1 --- Please select a device to execute kernel from: (1) ext_ssram Class: altera_avalon_cy7c1380_ssram Size: 2097152 bytes (2) ddr_sdram Class: ddr_sdram_component Size: 33554432 bytes (3) epcs_controller Class: altera_avalon_epcs_flash_controller Size: 2048 bytes Selection: 2 After that we have to congure the kernel by that command line, # config the kernel make ARCH=nios2nommu CROSS_COMPILE=nios2-linux-uclibc- menuconfig In the menu Device Drivers > Character devices > Serial drivers > we select a serial or a jtag console. If your user id and group id on Linux are not 500, change these to your id instead, Device Drivers > Block devices > (for 2.6.11-uc0)

Then nally we can save and exit our conguration and last but not least, compile our kernel, # compile the kernel make ARCH=nios2nommu CROSS_COMPILE=nios2-linux-uclibc- zImage

4.3

Ready to start

Now the compressed kernel image arch/nios2nommu/boot/zImage is ready to get downloaded to your hardware. At rst, download the sof le of your hardware to your board with quartusII programmer, then open a nios2 sdk shell, Go to the directory your linux home is mapped to e.g c: is /cygdrive/c/ and download the kernel image. cd /cygdrive/c/linux-2.6.x/arch/nios2nommu/boot nios2-download -g zImage nios2-terminal
Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 33

NIOS-CPU with additional hardware driven with Clinux

Installing Clinux toolchain

By loading this image, some boot messages will appear and nally a boot prompt will be shown.

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 34

NIOS-CPU with additional hardware driven with Clinux

Programming kernel driver

5
5.1
5.1.1

Programming kernel driver


Implementation of the driver
General

This section of the tutorial shows, how to program a driver for linux kernel 2.6. We recommend to print out the kernel module source (see appendix B), which is attached to this how to and to read the source simultaneously with this section. First of all you should know, that a kernel module is in principle just a c program with at least two functions, static int init mod init(void) and static void exit mod exit(void). (The names of the functions are specied by module init(mod init); and module exit(mod exit); where function pointers are given to the kernel) 5.1.2 Denes

We dene the major numbers for linking between le-system and driver: #define DATA MAJOR 240 - data device le gets major number 240 #define DIR MAJOR 241 - direction device le gets major 241 We need the addresses of the data and direction register in the avalon bus. This address is assigned when adding the pio eigen.vhd to the hardware specication in SOPC-builder (see section 5). #define DATA REGISTER 0x00801090 - data register is at address 0x00801090 #define DIR REGISTER 0x00801091 - direction register is at address 0x00801091 We need buffers to hold the data read from registers for copying into user-space. #define STRING LEN 5 - buffers are 5 bytes long 5.1.3 Function calls

The init function is called when the module is loaded into the kernel, e.g. with insmod modulename and the exit function is executed when unloading the module from the kernel, e.g. with rmmod modulename. This way it is possible to run a program in kernel-space, but it is still not possible to access the hardware from the user-space. To make that possible, it is necessary to extend the module to a driver which links the hardware registers into the linux lesystem. To get such a driver we need to register all device les we want to use to the IO-management of the kernel. This is done by register chrdev(DATA MAJOR, "iodata", &fops dat); for the data register and by register chrdev(DIR MAJOR, "iodir", &fops dir); for the direction register in modules init function. The rst parameter of these function calls
Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 35

NIOS-CPU with additional hardware driven with Clinux

Programming kernel driver

(DATA MAJOR and DIR MAJOR) are just integer values for linking the device les of the lesystem to the driver. The second parameter is the name, which identies the device le in kernel IO-management. The last parameter is a struct, including pointers to functions which are called when accessing the device les. static struct file_operations fops_dir = { .read= dir_read, .write= dir_write, .open= dir_open, .release= dir_release }; Function int dir open(..) is called when a process tries to open the device le. It checks, whether another process uses this le already, if so, it will return a busy signal to the process, which tries to open. If a process got successfully access to the device le, the data of the direction register is read with inb(DIR REGISTER) and stored as string in a buffer. Function size t dir read(..) is called when a process reads from device le. It copies every byte of the buffer (containing the data of the direction register) into userspace using the command put user(..). Normally the reason why we cannot just copy from a kernel space buffer into a user space buffer using memcpy would be, that the buffers are in different virtual address blocks. But due to the fact that we dont have a memory management unit (mmu), those buffers are in the same address block. Nevertheless we decided to program it like if we had a mmu, to allow debugging on a host-machine with mmu. Function size t dir write(..) is called when writing to the device le. It copies data from an user space buffer into a kernel space buffer using copy from user(..). The reason for not using memcpy is the same like for function dir read. Data is stored into direction register using outb(buffer,DIR REGISTER) after copying. Function int dir release(..) is called when a process closes the le. It unlocks the device le and the module. Same functions exist for the data register too. When unloading the driver the device les have to be unregistered from IO-management. To accomplish that, those two functions must be called in the modules exit function: unregister chrdev(DATA MAJOR,"iodata"); for unregistering the data device le and unregister chrdev(DIR MAJOR,"iodir"); for unregistering the direction device le.

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 36

NIOS-CPU with additional hardware driven with Clinux

Programming kernel driver

5.2

Adding device les to rootfs

Now we have to take care, that our device les are generated when booting the linux image on the target. Therefor you can add these two lines to /download/rootfs list: nod /dev/iodata 666 0 0 c 240 0 nod /dev/iodir 666 0 0 c 241 0 The lines say, that 2 device les are generated, /dev/iodata and /dev/iodir both with the Unix permissions 666, and the major numbers for associating the les with the driver, in this case 240 and 241. When building a new kernel, it will automatically create all device les like congured in /download/rootfs list.

5.3

Adding driver to kernel

To add the driver to the kernel sources, copy the source code to linux-source/drivers/misc/. Now we need to tell menucong something about the new kernel driver. Therefor the line obj-$(CONFIG IO) += io.o has to be added to the Makele in linux-source/drivers/misc/. And following lines to the Kcong le in linux-source/drivers/misc/ right above the endmenu statement: config IO tristate "IO module for custom IO" help Enable module to access custom IO.

5.4

Building the kernel

Change into the directory of the linux source and type: make ARCH=nios2nommu CROSS COMPILE=nios2-linux-uclibc- menuconfig Now the kernel conguration interface shows up. To enable the custom kernel driver change to Device Drivers --> Misc devices and press y when highlighting IO module for custom IO. Then press exit and save the conguration. To cross-compile the kernel type: make ARCH=nios2nommu CROSS COMPILE=nios2-linux-uclibc- zImage After kernel was successfully generated, the zImage including kernel and rootfs can be copied from: linux-source/arch/nios2nommu/boot/zImage. Page 37

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

NIOS-CPU with additional hardware driven with Clinux

User-space programs

6
6.1

User-space programs
General

Due to the fact, that there is not enough space on the target board for a whole compiler suite, it is necessary to cross-compile user-space programs on a host machine. To cross-compile any C source code, just run: nios2-linux-uclibc-gcc source.c -o output bin -elf2flt="-s 16000" -Wall After that you have to move the binary program into the rootlesystem, with e.g. mv output bin /rootfs/usr/bin/ and compile a new kernel (have a look a chapter above), what creates a new zImage with the kernel and the modied rootfs. After downloading the new zImage the command output bin should be available on the target.

6.2

Using custom IO

If you want to code a program using the custom hardware dened in pio eigen.vhd you can include the header le testing/pio eigen.h into your C program. It implements functions for reading and writing to the two device les /dev/iodata and /dev/iodir: unsigned char read dev(files file) returns the value as unsigned char of the device le you want to read from. The data type les is an enumeration consisting of dir le and dat le. e.g: int a=read dev(dat file); void write dev(files file, unsigned char val) writes the value of the byte val into the device le. e.g: write dev(dir file,240); Two example programs can be found in testing/ folder; test io output and test io input.

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 38

NIOS-CPU with additional hardware driven with Clinux

Using preinstalled VM

Using preinstalled VM

We created a virtual machine based on fedora core 4 for compiling Clinux to save time which would be needed to step through the installation process of the Clinux tool-chain. The virtual machine runs with qemu, an open source PC emulator compiled for different host systems, like linux or windows. You need at least 8GB of hard disk space on your host system to use this virtual machine.

7.1

Linux host system

1. extract the le qemu-0.8.1-i386.tar.gz from virtual machine dvd 1 to /: su - [root pw] cd / tar xvfz /media/cdrom/qemu-0.8.1-i386.tar.gz 2. copy the image-les fedora4 uclinux.img (dvd 1), fedora4 jack.img (dvd 2) and the start-script fedora4 uclinux.sh (dvd 1) into the same folder of your hard disk. 3. run the start-script (ensure that you are in the folder where the start-script and the images are): sh fedora4 uclinux.sh

7.2

Windows host system

1. we made a dvd with ext2 lesystem due to le size limitations on normal iso9660 lesystem, what concludes, that it isnt possible to read this dvds from windows system by default. It might work with the ext2 driver from http://www.fs-driver.org or with explore2fs. 2. unzip the le qemu-0.8.1-windows-3.zip from virtual machine dvd 1 to any folder of your hard disk. 3. copy the image les fedora4 uclinux.img (dvd 1), fedora4 jack.img (dvd 2) and the batch-script fedora4 uclinux.bat (dvd 1) into the folder where you extracted qemu to. 4. run the start-script fedora4 uclinux.bat by double clicking.

7.3

Usage

After executing the start-script, the virtual machine boots and after some time asks you for login. To work with the Clinux tool-chain you should login as jack with the password jack. The root account should only be used for system conguration purposes password for root is 123456.

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 39

NIOS-CPU with additional hardware driven with Clinux

Using preinstalled VM

7.4

Moving data

You can move data between the guest OS and the host OS by connecting from guest OS to host OS. You cannot connect from host OS to guest OS. Thus we suggest you to create a windows share if you are using windows as host OS or to use scp/sftp if you are using linux as host OS. Windows OS : 1. Create share on host OS, e.g. the folder c:\bla 2. Mount the share on guest OS: mount -o username=windows username //10.0.2.2/bla /mnt/tmp/ 3. Now you can copy data from your guest OS to the shared directory Linux OS : 1. Start the ssh daemon on your host OS: /etc/init.d/sshd start 2. Copy les this way: scp file you want to copy user@10.0.2.2:

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 40

NIOS-CPU with additional hardware driven with Clinux

Summary

Summary

In the early planning phase we assumed to get the most problems with the open source tools. Actually it was the other way round and we got disappointed in the commercial tools from Altera. Some problem may be due to a bad installation of our software. Unfortunately we did not have the time to set up a new software environment to verify this. Finally we nished our project successfully because we met most requirements. The things you can do with this howto are: Create own VHDL hardware Add own hardware to a Nios II processor Write a kernel module for own hardware Build Clinux for Nios II processor Things that would be nice to have in the future: Program Nios II conguration into ash memory to save data on power off. Add network support to Nios II to add own software to Clinux without building a new kernel. In the end we would give some tips to people who want to take this howto as basis for further projects. Our strategy to constitute two teams exposed to be the right one. Things are much easier if you just have to care about hardware or software. We also found out that it is very helpful you know the used software tools. You will save a lot of time of trying to gure out silly problems.

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 41

NIOS-CPU with additional hardware driven with Clinux

References

Addendum

References
[1] Ofcial altera page: http://www.altera.com [2] Support for nearly everything ;) http://www.wikipedia.org [3] Support for things wikipedia doesnt know: http://www.google.com [4] Ofcial Clinux page: http://uclinux.org/ [5] Community forum about Nios II: http://www.niosforum.com/ [6] Linux Kernel Module Programming Guide: http://www.tldp.org/LDP/lkmpg/2.6/html/x569.html [7] Quartus II Howto (german): http://www.elektor.de/Portals/0/Magazine/Downloads/2006/060025-12DE.pdf [8] Linux Driver Development (german): http://ezs.kr.hsnr.de/TreiberBuch/html/ [9] Nios 2 UClinux port guide (Account required): http://forum.niosforum.com/forum/index.php?showtopic=3174 [10] Nios 2 UClinux port: http://scorpius.homelinux.org/marc/nios2.html [11] GHDL a open source VHDL simulator: http://ghdl.free.fr/ [12] QEMU a processor emulator: http://fabrice.bellard.free.fr/qemu/ [13] Avalon Interface Specication: http://www.altera.com/literature/manual/mnl avalon spec.pdf [14] Nios II Hardware Development Tutorial: http://www.altera.com/literature/tt/tt nios2 hardware tutorial.pdf

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 42

NIOS-CPU with additional hardware driven with Clinux

VHDL Code

VHDL Code
pio eigen.vhd 03.05.2006 8 Bit parallel IO-Interface for NIOS II Peter Feuerer, Steffen Gutmann Ronny Schroeder, Sascha Haensch -

10

library from Altera denes function to std logic library altera vhdl support; use altera vhdl support.altera vhdl support lib.all; library ieee; use ieee.std logic 1164.all; use ieee.std logic arith.all; use ieee.std logic unsigned.all; dene interface entity pio eigen is port ( inputs: signal address : IN STD LOGIC VECTOR (1 DOWNTO 0); signal chipselect : IN STD LOGIC; signal clk : IN STD LOGIC; signal reset n : IN STD LOGIC; signal write n : IN STD LOGIC; signal read n : IN STD LOGIC; signal writedata : IN STD LOGIC VECTOR (7 DOWNTO 0); outputs: signal out port : INOUT STD LOGIC VECTOR (7 DOWNTO 0); signal readdata : OUT STD LOGIC VECTOR (7 DOWNTO 0) ); end entity pio eigen;
40

20

30

dene functionality architecture europa of pio eigen is signal dir reg : STD LOGIC VECTOR (7 DOWNTO 0); signal data out : STD LOGIC VECTOR (7 DOWNTO 0); signal data in : STD LOGIC VECTOR (7 DOWNTO 0); begin process (clk, reset n) begin
50

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 43

NIOS-CPU with additional hardware driven with Clinux

VHDL Code

if reset n = 0 then clear the output register and the direction register data out <= std logic vector("00000000"); dir reg <= std logic vector("00000000"); rising edge detects read or write transfer elsif clkevent and clk = 1 then WRITE to data register if chipselect = 1 and write n = 0 and address = 00 if std logic(((chipselect AND NOT write n) AND to std logic((((std logic vector("000000000000000000000000000000") & (address)) = std logic vector("00000000000000000000000000000000")))))) = 1 then if dir reg(x) = 1 (= output) then data out(x) <= writedata(x) else data out(x) <= Z (High Impedance) if dir reg(0) = 1 then data out(0) <= writedata(0); else data out(0) <= Z; end if; if dir reg(1) = 1 then data out(1) <= writedata(1); else data out(1) <= Z; end if; if dir reg(2) = 1 then data out(2) <= writedata(2); else data out(2) <= Z; end if; if dir reg(3) = 1 then data out(3) <= writedata(3); else data out(3) <= Z; end if; if dir reg(4) = 1 then data out(4) <= writedata(4); else data out(4) <= Z; end if; if dir reg(5) = 1 then data out(5) <= writedata(5); else data out(5) <= Z; end if; if dir reg(6) = 1 then data out(6) <= writedata(6); else data out(6) <= Z; end if; if dir reg(7) = 1 then data out(7) <= writedata(7);

60

70

80

90

100

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 44

NIOS-CPU with additional hardware driven with Clinux

VHDL Code

else data out(7) <= Z; end if; READ from data register if chipselect = 1 and read n = 0 and address = 00 elsif std logic(((chipselect AND NOT read n) AND to std logic((((std logic vector("000000000000000000000000000000") & (address)) = std logic vector("00000000000000000000000000000000")))))) = 1 then readdata(7 DOWNTO 0) <= data in; WRITE to direction register if chipselect = 1 and write n = 0 and address = 01 elsif std logic(((chipselect AND NOT write n) AND to std logic((((std logic vector("000000000000000000000000000000") & (address)) = std logic vector("00000000000000000000000000000001")))))) = 1 then dir reg <= writedata(7 DOWNTO 0); if dir reg(x) = 0 (= Input) then data out(x) <= Z (High Impedance) every input driver is set to High Impedance if dir reg(0) = 0 then data out(0) <= Z; end if; if dir reg(1) = 0 then data out(1) <= Z; end if; if dir reg(2) = 0 then data out(2) <= Z; end if; if dir reg(3) = 0 then data out(3) <= Z; end if; if dir reg(4) = 0 then data out(4) <= Z; end if; if dir reg(5) = 0 then data out(5) <= Z; end if; if dir reg(6) = 0 then data out(6) <= Z; end if; if dir reg(7) = 0 then data out(7) <= Z; end if; READ from direction register

110

120

130

140

150

160

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 45

NIOS-CPU with additional hardware driven with Clinux

VHDL Code

if chipselect = 1 and read n = 0 and address = 01 elsif std logic(((chipselect AND NOT read n) AND to std logic((((std logic vector("000000000000000000000000000000") & (address)) = std logic vector("00000000000000000000000000000001")))))) = 1 then readdata(7 DOWNTO 0) <= dir reg; end if; end if; end process; ll out port with data out and data in with out port independently from the process every time and in parallel out port <= data out; data in <= out port; end europa;

170

180

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 46

NIOS-CPU with additional hardware driven with Clinux

Kernel module code

Kernel module code


/* /* /* /* /* /* /* /* /* /* /* /* Copyright (C) 2006 Sascha Haensch, Peter Feuerer, Ronny Schroeder, Steffen Gutmann */ This program is free software; you can redistribute it and/or modify */ it under the terms of the GNU General Public License as published by */ the Free Software Foundation; either version 2 of the License, or */ (at your option) any later version. */ This program is distributed in the hope that it will be useful, */ but WITHOUT ANY WARRANTY; without even the implied warranty of */ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. GNU General Public License for more details. */ You should have received a copy of the GNU General Public License */ along with this program; if not, write to the Free Software */ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA

10

/* /* /* /*

uncomment following line to use the kernelmodule without */ io (inb / outb) functions, needed for debug purposses on host */ machine. */ #dene DEBUG */ <linux/kernel.h> <linux/module.h> <linux/fs.h> <asm/uaccess.h>
20

#include #include #include #include

/* major numbers for identifying the device les */ /* mknod /dev/iodata c 240 0 */ #dene DATA MAJOR 240 /* mknod /dev/iodir c 241 0 */ #dene DIR MAJOR 241
30

/* register addresses */ #dene DATA REGISTER 0x00801090 #dene DIR REGISTER 0x00801091 /* max buffer length */ #dene STRING LEN 5

MODULE AUTHOR("Sascha Haensch, Peter Feuerer, Ronny Schroeder, Steffen Gutmann"); MODULE LICENSE("GPL"); MODULE DESCRIPTION("Module which creates devicehandler for /dev/iodata and /dev/iodir for 8 I/O pins"); MODULE SUPPORTED DEVICE("none"); /* dene buffers for the strings sended to user */ char dat string[STRING LEN]="0\n"; char dir string[STRING LEN]="0\n"; char* dat ptr=dat string; char* dir ptr=dir string; /* device les open? */

40

50

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 47

NIOS-CPU with additional hardware driven with Clinux

Kernel module code

int dir is open = 0; int dat is open = 0; /* convert string to integer */ static int atoi(const char *name) { int val = 0; for (;;name++) { switch (*name) { case 0. . .9: val = 10*val+(*name0); break; default: return val; } } } /* convert byte to string */ void itoa(char *name, unsigned char value) { int i,j=0; for(i=100;i>0;i/=10) { name[j++]=0+value/i; value=value(value/i)*i; if(name[0]==0 && i!=1) j=0; } name[j++]=\n; name[j]=0; } /* called when data device le is opened */ static int dat open(struct inode *inode, struct le *le) { unsigned char value; if (dat is open++) return EBUSY; /* catch new information from data register */ #ifndef DEBUG value=inb(DATA REGISTER); itoa(dat string,value); #endif dat ptr=dat string; try module get(THIS MODULE); return 0; }

60

70

80

90

100

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 48

NIOS-CPU with additional hardware driven with Clinux

Kernel module code

/* called when process closes data device le */ static int dat release(struct inode *inode, struct le *le) { dat is open; module put(THIS MODULE); return 0; } /* called when a process reads from data le */ static ssize t dat read(struct le *lp, char *buffer, size t length, loff t * offset) { /* Number of bytes actually written to the buffer */ int bytes read = 0; /* If were at the end of the message, return 0 signifying end of le */ if (*dat ptr == 0) return 0; while (length && *dat ptr) { /* The buffer is in the user data segment, not the kernel */ /* segment so * assignment wont work. /* put user which copies data from the kernel data segment to */ /* the user data segment. */ put user(*(dat ptr++), buffer++); bytes read++; } /* return count of bytes, sent to user */ return bytes read; } /* called when a process writes to data le*/ static ssize t dat write(struct le *lp, const char *buff, size t len, loff t * off) { int not copied=0; if(len > (STRING LEN1)) len=STRING LEN1; /* copy data from user into buffer dat string */ not copied=copy from user(dat string,buff,len); dat string[len]=\0; /* output the value of the number in buffer dat string */ /* to address of the direction register */ #ifndef DEBUG outb((unsigned char)atoi(dat string),DATA REGISTER); #endif

110

120

140

150

return lennot copied; }


160

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 49

NIOS-CPU with additional hardware driven with Clinux

Kernel module code

/* called when direction device le is opened */ static int dir open(struct inode *inode, struct le *le) { unsigned char value;
170

if (dir is open++) return EBUSY; /* catch new information from direction register */ #ifndef DEBUG value=inb(DIR REGISTER); itoa(dir string,value); #endif dir ptr=dir string; try module get(THIS MODULE); return 0; } /* called when process closes direction device le */ static int dir release(struct inode *inode, struct le *le) { dir is open; module put(THIS MODULE); return 0; } /* called when a process reads from direction le */ static ssize t dir read(struct le *lp, char *buffer, size t length, loff t * offset) { /* Number of bytes actually written to the buffer */ int bytes read = 0;
200 190 180

/* If were at the end of the message, return 0 signifying end of le */ if (*dir ptr == 0) return 0; while (length && *dir ptr) { /* The buffer is in the user data segment, not the kernel */ /* segment so * assignment wont work. /* put user which copies data from the kernel data segment to */ /* the user data segment. */ put user(*(dir ptr++), buffer++); bytes read++; } /* return count of bytes, sent to user */ return bytes read; }

210

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 50

NIOS-CPU with additional hardware driven with Clinux

Kernel module code

/* called when a process writes to direction le*/ static ssize t dir write(struct le *lp, const char *buff, size t len, loff t * off) { int not copied=0; if(len > (STRING LEN1)) len=STRING LEN1; /* copy data from user into buffer dir string */ not copied=copy from user(dir string,buff,len); dir string[len]=\0; /* output the value of the number in buffer dir string */ /* to address of the direction register */ #ifndef DEBUG outb((unsigned char)atoi(dir string),DIR REGISTER); #endif return lennot copied; }

220

230

/* denitions, which functions are called for /dev/iodata */ static struct le operations fops dat = { .read= dat read, .write= dat write, .open= dat open, .release= dat release }; /* denitions, which functions are called for /dev/iodir */ static struct le operations fops dir = { .read= dir read, .write= dir write, .open= dir open, .release= dir release };

240

250

/* initialize the module */ static int init mod init(void) { if(register chrdev(DATA MAJOR, "iodata", &fops dat)) { printk("register_chrdev of iodata failed!\n"); return EIO; } if(register chrdev(DIR MAJOR, "iodir", &fops dir)) { printk("register_chrdev of iodir failed!\n"); return EIO; } /* workaround for initializing all pins as input */ #ifndef DEBUG

260

270

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 51

NIOS-CPU with additional hardware driven with Clinux

Kernel module code

outb(255,DATA REGISTER); outb(0,DATA REGISTER); #endif return 0; } /* exit the module */ static void exit mod exit(void) { unregister chrdev(DATA MAJOR,"iodata"); unregister chrdev(DIR MAJOR,"iodir"); } /* what are the module init/exit functions */ module init( mod init ); module exit( mod exit );
290 280

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 52

NIOS-CPU with additional hardware driven with Clinux

The Expansion Board

C
C.1

The Expansion Board


Description

Our expansion board provides eight independent channels which are congureable as either an input or an output. Each channel consists of a jumper, a led, a pushbutton and two resistors.

C.2

Bill Of Materials

8x resistor 180 ohm 8x resistor 10k ohm 8x low current led red 3mm 8x pushbutton (APEM - PHAP3301) 8x 2-pole jumper 8x 3-pole strip 1x 10-pole strip 4x spacer 10mm 4x bolt M3x6 pcb with provided layout

C.3

Connection between Expansion Board and Nios II Evaluation Kit

We used the multipoint connector J5 on the prototype area of the Nios II Evaluation Kit. J5 on Evaluation Board Connector on Expansion Board Vcc3 3 (Pin 2) Vcc Ground (Pin 3, 7, 10, 12, 13, 17) Ground 4 1 6 2 8 3 14 4 16 5 18 6 1 7 5 8

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 53

NIOS-CPU with additional hardware driven with Clinux

The Expansion Board

C.4

Schematic

Figure 29: schematic of the expansion board

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 54

NIOS-CPU with additional hardware driven with Clinux

The Expansion Board

C.5

PCB-Layout

Figure 30: pcb of the expansion board

Peter Feuerer, Steffen Gutmann, Sascha Haensch, Ronny Schroeder

Page 55

Das könnte Ihnen auch gefallen