Download - UClinux Nios2 Custom Hardware
-
Clinux on NIOS2 with custom hardware and
kernel module
Johan GranathApplied Electronics for Embedded Systems
AGSTU School of Higher Vocational EducationMalmo, [email protected]
February 18, 2013
Abstract
This document describes how to set up a NIOS2-CPU system with MMU foruse with Clinux. It includes a simple custom hardware written in VHDL,connected to the Avalon bus, and a kernel module to be able to interface withthe custom hardware from user-space. The custom hardware controls someLEDs on a Altera development board (DE2-115), and should be fairly simpleto adapt to other circumstances.
1
-
Contents
1 Specification 3
2 QSys - building the system 42.1 OnChip RAMs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42.2 CPU . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52.3 SDRAM . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52.4 UP clocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62.5 JTAG UART . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.6 Timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.7 MMC SPI . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72.8 UART . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82.9 Custom LED component . . . . . . . . . . . . . . . . . . . . . . . 9
2.9.1 Create new component . . . . . . . . . . . . . . . . . . . . 92.10 Set properties of led component . . . . . . . . . . . . . . . . . . . 112.11 Finishing the system . . . . . . . . . . . . . . . . . . . . . . . . . 112.12 Connecting wires . . . . . . . . . . . . . . . . . . . . . . . . . . . 11
3 Clinux - installation and configuration 133.1 Cloning the repositories . . . . . . . . . . . . . . . . . . . . . . . 133.2 Preparing the dts . . . . . . . . . . . . . . . . . . . . . . . . . . . 143.3 Configuring Clinux . . . . . . . . . . . . . . . . . . . . . . . . . 153.4 Building Clinux . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.5 Loading Clinux onto the board . . . . . . . . . . . . . . . . . . 18
3.5.1 SD-card as root file system . . . . . . . . . . . . . . . . . 183.5.2 Boot from memory . . . . . . . . . . . . . . . . . . . . . . 18
4 Custom hardware setup 204.1 Kernel configuration . . . . . . . . . . . . . . . . . . . . . . . . . 204.2 Add device files to root file system . . . . . . . . . . . . . . . . . 204.3 Adding the source . . . . . . . . . . . . . . . . . . . . . . . . . . 204.4 Building the kernel . . . . . . . . . . . . . . . . . . . . . . . . . . 204.5 Testing the driver . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
A LED component VHDL code 21
B LED component kernel driver C code 22
2
-
1 Specification
The system should be based on NIOS2, more specifically the NIOS2(f) variant.It should use a MMU (Memory Management Unit) to be able to facilitate virtualmemory in Clinux. The following tasks are going to be implemented:
Build a NIOS2-system with MMU and peripherals in QSys Build a custom hardware component that controls some LEDs, make it
Avalon-ready
Build and configure Clinux for NIOS2 with MMU Write a kernel driver (module) to control the LED-component.
The hardware used in this project is Alteras DE2-115 board. However it shouldbe pretty easy to adapt to other development boards in the DE* range.
3
-
2 QSys - building the system
In this project QSys is used instead of SOPC builder. QSys is the new wayof building NIOS2-based systems. The following features and components arerequired for this particular setup:
NIOS2(f) CPU with MMU OnChip RAM (MMU) SDRAM JTAG-UART UART Timer UP Clocks MMC SPI (SD-card) Custom LED componentPlease note that the above specifies the requirements for this particular
project. Clinux is able to function without some of the above (i.e customhardware, UART, MMC SPI).
2.1 OnChip RAMs
Two OnChip RAMs are used. One for the reset- and exception vectors and onefor the MMU TLB. The reset/exception OnChip RAM was made 4096 bytesbig and the MMU TLB OnChip 1024 bytes. Note that the MMU TLB OnChipRAM is a dual-port RAM. See figure 1 (reset/exception) and 2 (MMU TLB).
Figure 1: OnChip RAM
4
-
Figure 2: OnChip RAM TLB
2.2 CPU
The CPU is the fast variant (NIOS2(f)). Check that MMU is used and makesure that the reset-, exception vectors and TLB are located at their respectiveOnChip RAM. Connect data master to s1-port and instruction master to s2-porton TLB OnChip RAM. Also connect the instruction master and data master toport s1 of the regular OnChip RAM. See figure 3.
Figure 3: CPU settings
2.3 SDRAM
To be able to function, Clinux needs some RAM. We make use of the SDRAMon the DE2-115 board. It has 128MB of SDRAM. It should be possible with
5
-
less SDRAM (even SRAM) but at least 8MB is needed for a extremely minimalsystem. More RAM than that is recommended. Instanciate a SDRAM con-troller. Then choose custom and fill in the values as seen below in figure 4 and5. Please note that these settings are for the DE2-115 SDRAM, other settingsapply if you use another board.
Figure 4: SDRAM profile
Figure 5: SDRAM timing
Also, export the wires from the SDRAM component. We will later connectthem to the SDRAM controller on the board.
2.4 UP clocks
This core will set up the clock that is needed for the SDRAM to functioncorrectly. It is found within Alteras University Program (UP). Instanciate thecore and select your board and then SDRAM clock. See figure 6.
6
-
Figure 6: UP clocks
Worth noting here is that the UP Clocks core provides us with a systemclock as well. Use this clock (sys clk) to all other components except the UPClocks component itself. I.e the other components should be clocked on sys clkfrom UP Clocks instead of directly from the 50Mhz clock provided by the board.
2.5 JTAG UART
This component is used for connecting to Clinux. The terminal so to speak.This project also includes a RS232 UART since the JTAG UART can be a bitflaky (it sends random characters when not supposed to, atleast on my system).Nevertheless, instanciate a JTAG UART and connect IRQ 1 to the CPU.
2.6 Timer
Clinux needs a timer to function. This timer needs to be full-featured. Seefigure 7. Connect the IRQ to the CPU.
Figure 7: Timer settings
2.7 MMC SPI
This component is optional, but is needed if the system needs to make per-manent changes to the filesystem. It is basically a component that will makeit possible to use a filesystem on a SD-card (or MMC) as root filesystem in
7
-
Clinux. Instanciate the component (called SPI 3-wire) and make changes ac-cording to figure 8.
Figure 8: MMC (SD-card) SPI 3-wire
Also, export the wires (Click to export). We will later connect them to theSD-card controller. Connect IRQ 2 to the CPU.
2.8 UART
For a more reliable terminal than JTAG UART, a real UART via RS232 willbe used. This component is also optional. Start by instanciating a UART andmake changes according to figure 9.
8
-
Figure 9: UART RS323
Export the wires and connect IRQ 3 to the CPU.
2.9 Custom LED component
The LED component is a proof-of-concept component, it has no real value exceptfor educational purposes. Its functionality is to take input from the Avalon busand output those values on the LEDG LEDs on the DE2-115 board. It is ofcourse also optional, and not needed for Clinux to operate. However if thereader is about to add some custom component to a Clinux system, theseguidelines might be useful. First, the component needs to be written in VHDL.See appendix A for the VHDL code.Next, it needs to be imported in QSys.
Create a directory in your project directory called ip\led component\HDL.Next put the source code there (i.e led.vhd).
2.9.1 Create new component
In QSys choose File-New component. Fill in the boxes as seen in figure 10.
9
-
Figure 10: New component settings
Then add the led.vhd VHDL file and click Analyse Synthesis Files. Seefigure 11.
Figure 11: New component files
Then select the corresponding Avalon signals for each signal in the top-levelhierarchy. Note that LEDG has to be set to conduit. See figure 12.
Figure 12: New component signals
Finally, check that the clocks and reset signals are present (associated clock/reset).
10
-
See figure 13.
Figure 13: New component clocks/reset
Then press finish. The component should be visible and the possiblility toinstanciate it will be present. Instanciate it and connect s1 to data master, andalso export the wires, which we will connect later.
2.10 Set properties of led component
To make our kernel driver recognize the led component it needs to have cor-rect properties in the DeviceTree. This can be accomplished by editing theled hw.tcl. Add the following sections to it.
set_module_assignment embeddedsw.dts.vendor "ALTR"set_module_assignment embeddedsw.dts.name "led"set_module_assignment embeddedsw.dts.group "led"
2.11 Finishing the system
To finish, select Assign Base Addresses and press finish.
2.12 Connecting wires
For this project a BDF (Block Diagram) will connect the wires to the respectivecontrollers on the board. This is just a matter of reading the DE2-115 manual.See figure 14.
11
-
Figure 14: Schematic pin connections
12
-
3 Clinux - installation and configuration
To be able to build Clinux the following are required:
Linux build box (Fedora 17 in our case) make version 3.81 or less Clinux distribution Toolchain (precompiled)This chapter explains installing and configuring Clinux without the custom
hardware. We want to make sure it runs before we make those changes.
3.1 Cloning the repositories
There is a community git server that has all of the prerequisites. It is locatedat http://sopc.et.ntust.edu.tw/. Start by cloning the git repositories thatwe need.
1. Clone the trunk branch of Clinux.git clone -b trunk git://sopc.et.ntust.edu.tw/git/uClinux-dist.git
2. Clone the toolchain (MMU variant).git clone git://sopc.et.ntust.edu.tw/git/toolchain-mmu.git
3. Clone the linux-2.6 repository.git clone git://sopc.et.ntust.edu.tw/git/linux-2.6.git
4. We also need the sopc2dts tool.git clone git://sopc.et.ntust.edu.tw/git/tools.git
Next, check that the correct branches are used. For Clinux, trunk shouldbe used, for toolchain-mmu, master is used and for linux-2.6, nios2 is used.
# cd uClinux-dist# git branch* trunk...# cd toolchain-mmu# git branch* master...# cd linux-2.6# git branch* nios2
13
-
3.2 Preparing the dts
DeviceTree is a way of describing the hardware in an embedded system. Thisinformation is passed to the kernel during build, so it is needed before we startto build Clinux. QSys provides a .sopcinfo file which has to be convertedto a .dts (DeviceTree). A boardinfo file can be created for later use. Readmore about boardinfo at http://www.alterawiki.com/wiki/Sopc2dts. Use thesopc2dts utility with the GUI feature.
$ java -jar sopc2dts.jar --gui
Next, select Choose file and open your .sopcinfo file from QSys. See figure15.
Figure 15: sopc2dts GUI
We have to add a mmc-spi-slot to the dts. Select Boardinfo, SPI andthen select your SPI component. Next click Add to add a mmc-spi-slot.See figure 16.
14
-
Figure 16: sopc2dts GUI
Finally, select Output and save your dts file.
3.3 Configuring Clinux
Before building the kernel some changes are needed. The first thing that needsto be done is to set the PATH environment variable so that the build system findsthe toolchain.
# export PATH=$PATH:/path/to/nios2/toolchain/bin
Some other changes in the kernel configuration is needed.
Set start of SDRAM memory (CONFIG MEM BASE) Compile and link DTB into kernel image (CONFIG DTB SOURCE BOOL) Set DTB file to be used above (CONFIG DTB SOURCE) Set MMU support (CONFIG MMU) Set kernel commandline (CONFIG CMDLINE) Set link address offset (CONFIG BOOT LINK OFFSET) Set SPI support (if MMC SPI is used) (CONFIG SPI) Set SPI Altera support (if MMC SPI is used) (CONFIG SPI ALTERA) Set MMC support (if MMC SPI is used) (CONFIG MMC) Set MMC over SPI support (if MMC SPI is used) (CONFIG MMC SPI)
15
-
These changes can be made with make menuconfig. Please note that makeversion 3.81 or less has to be used! The first configuration menu is for settingplatform and vendor. Choose libc - none here. See figure 15 and 16.
Figure 17: Vendor/Platform selection
Figure 18: Libc/Kernel configuration selection
16
-
If the applications shipped with Clinux needs to change, select CustomizeApplication/Library Settings. For the purpose of this document, the de-fault application settings are used. If Customize Kernel Settings were cho-sen, the following menu is available (figure 17).
Figure 19: Kernel configuration
Here all the changes has to be made. The Start of SDRAM Memory needsto be set to whatever memory location QSys chose for the SDRAM. Have a lookin your DTS to find out. The kernel commandline can be one of two possiblesettings. It depends on if we want it to boot from SD-card or from memory, athird alternative is also possible - to use JTAG UART as console.
1. To boot from memory with UART as serial console.
debug console=ttyAL0,115200
2. To boot from SD-card with UART as serial console.
debug console=ttyAL0,115200 root=/dev/mmcblk0 rootdelay=2
3. To boot from memory with JTAG UART as serial console.
debug console=ttyJ0,115200
The other settings also have to be made. To search and find where in theconfiguration menu tree a specific configuration option is, use / to search aftera CONFIG * option. Then do the appropriate changes.
17
-
3.4 Building Clinux
After the configuration is done, the build can start. Hopefully without anycompilation errors. If you get compilation errors, there is most likely somepackage missing on your build machine. These packages are confirmed to beneeded (Fedora 17).
git-all git-gui make gcc ncurses-devel bison byacc flex \gawk gettext ccache zlib-devel gtk2-devel lzo-devel \pax-utilslibglade2-devel uboot-tools
To start the build (again with make version 3.81 or less):
# make...Kernel: arch/nios2/boot/zImage is ready...
When done, the above text is printed. This means your build was successful.
3.5 Loading Clinux onto the board
This can be done in two ways. Since we have configured MMC SPI support theinitramfs can be copied onto a SD-card, then use that as a root file system.
3.5.1 SD-card as root file system
The initramfs is located in the relative path (in uClinux-dist directory)linux-2.6/usr/initramfs data.cpio. First the SD-card has to be preparedto be able to copy the contents onto it. Please note that /dev/sdb could bedifferent in your system.
$ mke2fs /dev/sdb$ mount /dev/sdb /mnt$ cd /mnt$ cat /path/to/initramfs_data.cpio | cpio -id$ umount /mnt
The SD-card is now ready to be booted from. Proceed to Boot from memory.
3.5.2 Boot from memory
First, the board has to be loaded with the .sof file from Quartus.
$ nios2-configure-sof /path/to/soffile.sof
Next, we have to load the kernel into the memory.
$ nios2-download /path/to/zImage
To be able to see some output, use a terminal program, like minicom (or nios2-terminal if you chose JTAG UART as serial console). Note that ttyUSB0 couldbe different in your system.
$ minicom -D /dev/ttyUSB0
18
-
You should see Clinux boot up.
...Welcome to
____ _ _/ __| ||_|
_ _| | | | _ ____ _ _ _ _| | | | | | || | _ \| | | |\ \/ /| |_| | |__| || | | | | |_| |/ \| ___\____|_||_|_| |_|\____|\_/\_/| ||_|
For further information check:http://www.uclinux.org/
BusyBox v1.18.4 (2013-02-13 19:40:16 CET) hush - the humble shellEnter help for a list of built-in commands.
root:/>
19
-
4 Custom hardware setup
Now that we have a functioning Clinux system up and running, its possible toadd support for the custom hardware that we added in QSys (LED component).We will do some changes to the kernel configuration and and a kernel driver forthis component.
4.1 Kernel configuration
There is a few changes that has to be made to include the code into the kernelbuild.
1. Add option to Kconfig in linux-2.6\source\drivers\misc
config LEDtristate "LED custom hardware"help
LED custom hardware
2. Add object file to Makefile in linux-2.6\source\drivers\misc
obj-$(CONFIG_LED) += led.o
4.2 Add device files to root file system
The kernel driver will make use of a device file to communicate with the hard-ware, so a device file needs to be created. Add the following line to vendors\Altera\nios2\device table.txt/dev/led c 666 0 0 250 0 - - -
4.3 Adding the source
The source of the device driver needs to be put in linux-2.6\source\drivers\misc,and be called led.c. See source code in appendix B.
4.4 Building the kernel
To include the kernel driver, the kernel needs to be rebuilt. In the configurationchoose the CONFIG LED option and save your changes. The kernel should nowinclude the code in the build.
$ make menuconfig$ make
4.5 Testing the driver
If the build was successful, the driver should be able to output some values onthe LEDG LEDs from user-space. To test the function type in the following.
$ echo 1 > /dev/led
The LEDG should now show 1, i.e the first LED should be lit.
20
-
A LED component VHDL code
library ieee;use ieee.std_logic_1164.all;
entity led isport(
clock_50 : in std_logic;reset_n : in std_logic;avalon_cs_n : in std_logic;avalon_addr : in std_logic_vector(0 downto 0);avalon_write_n : in std_logic;avalon_din : in std_logic_vector(7 downto 0);LEDG : out std_logic_vector(7 downto 0)
);end entity led;
architecture led_rtl of led isbegin
led_p : process(clock_50, reset_n)begin
if reset_n = 0 thenLEDG 0);
elsif rising_edge(clock_50) thenif avalon_cs_n = 0 then
if avalon_write_n = 0 and avalon_addr = "0" thenLEDG
-
B LED component kernel driver C code
#include #include #include #include #include #include #include #include #include #include
MODULE_AUTHOR("Johan Granath");MODULE_LICENSE("GPL");MODULE_DESCRIPTION("LEDG[7..0] driver for Altera DE2-115");MODULE_SUPPORTED_DEVICE("none");
#define LED_MAJOR 250
static ssize_t led_write(struct file *, const char *, size_t, loff_t *);static char led_str[3];int *led_mem=0;
static struct of_device_id led_of_match[] __devinitdata ={
{ .compatible = "ALTR,led-1.0", },{}
};MODULE_DEVICE_TABLE(of, led_of_match);
static struct file_operations fops_led ={
.write = led_write,};
static ssize_t led_write(struct file *fp, const char *buf, size_t len, \loff_t *offset)
{int not_copied, led_value;
not_copied=copy_from_user(led_str, buf, len);led_str[len] = \0;led_value = (int) simple_strtoul(led_str, NULL, 10);
iowrite8(led_value, led_mem);
return len-not_copied;}
22
-
static int __devinit led_drv_probe(struct platform_device *op){
struct resource *res;
if(!of_match_device(led_of_match, &op->dev))return -ENODEV;
res = platform_get_resource(op, IORESOURCE_MEM, 0);if(!res)
return -ENODEV;
if(!request_mem_region(res->start, resource_size(res), "led"))return -ENOMEM;
led_mem = of_iomap(op->dev.of_node, 0);if(!led_mem)
return -ENOMEM;
if(register_chrdev(LED_MAJOR, "led", &fops_led)){
printk("register_chrdev: led failed\n");return -EIO;
}
return 0;}
static int __devinit led_drv_remove(struct platform_device *op){
struct resource *res;
res = platform_get_resource(op, IORESOURCE_MEM, 0);if(!res)
return -ENODEV;
release_mem_region(res->start, resource_size(res));
return 0;}
static struct platform_driver led_platform_driver ={
.probe = led_drv_probe,
.remove = led_drv_remove,
.driver ={
.name = "led",
.owner = THIS_MODULE,
.of_match_table = led_of_match,
23
-
},};
static int __init mod_init(void){
int ret;ret = platform_driver_register(&led_platform_driver);return ret;
}
static void __exit mod_exit(void){
platform_driver_unregister(&led_platform_driver);unregister_chrdev(LED_MAJOR, "led");
}
module_init(mod_init);module_exit(mod_exit);
24
SpecificationQSys - building the systemOnChip RAMsCPUSDRAMUP clocksJTAG UARTTimerMMC SPIUARTCustom LED componentCreate new component
Set properties of led componentFinishing the systemConnecting wires
Clinux - installation and configurationCloning the repositoriesPreparing the dtsConfiguring ClinuxBuilding ClinuxLoading Clinux onto the boardSD-card as root file systemBoot from memory
Custom hardware setupKernel configurationAdd device files to root file systemAdding the sourceBuilding the kernelTesting the driver
LED component VHDL codeLED component kernel driver C code