Difference between revisions of "A simple design with Wishbone bus"

From ArmadeusWiki
Jump to: navigation, search
 
(55 intermediate revisions by 5 users not shown)
Line 1: Line 1:
 
[[Category: FPGA]]
 
[[Category: FPGA]]
{{Under_Construction}}
 
  
This article intended to explain how to design Wishbone compatible  
+
This article is intended to explain how to design Wishbone compatible components with simple example.  
components with simple example.  
+
The VHDL source code can be found in firmware/wishbone_example from  [https://gitlab.com/armadeus/armadeus-bsp our gitlab repository].
The VHDL code sources can be found in sourceforge
+
[http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/firmware/wishbone_example/ tree].
+
  
Description of wishbone structure for ARMadeus can be found [[FpgaArchitecture#Le_bus_Wishbone | here]] in french.
+
Description of the Wishbone structure for Armadeus APF boards can be found [[FpgaArchitecture#Le_bus_Wishbone | here]] (in french).
  
 
== General structure ==
 
== General structure ==
  
The main functionality of this component is to do the same things
+
The main functionality of this component is to allow to switch-on a LED when a button is pressed.
that [[FPGA_and_led | benoît]] project : switch on a LED when a button is  
+
pressed.
+
  
But to learn about designing Wishbone component and linux driver, the design
+
When button is pressed, the component ''button'' send interrupt signal to
is little bit more complicated (!).
+
 
+
When button is pressed, the component ''button'' send interrupt signal to
+
 
''irq_mngr''. ''irq_mngr'' will toggle a flag and send interruption to
 
''irq_mngr''. ''irq_mngr'' will toggle a flag and send interruption to
'''i.mx''' processor. A Linux driver on '''i.mx''' will read ''irq_mngr'' and
+
'''i.MX''' processor. A Linux driver on '''i.MX''' will read ''irq_mngr'' and
acknowledge irq by writing '1' on a register. And finally, Linux driver will
+
acknowledge irq by writing '1' on the corresponding register. And finally, Linux driver will
toggle LED value by writing on ''led'' register.
+
toggle LED value by writing in ''led'' register.
  
[[image:Wb_buttonled_top.png|center|frame|'''figure 1''' - ''Schematics of wishbone example''|500px]]
+
[[image:Wb_buttonled_top.png|700px|center|thumb|'''figure 1''' - ''Schematics of wishbone example. /!\ Bus signals are wrong for the APF51 because addr and data are multiplexed.'']]
  
 
''imx_wrapper'', ''syscon'' and ''irq_mngr'' are standards
 
''imx_wrapper'', ''syscon'' and ''irq_mngr'' are standards
 
ARMadeus-Wishbone IPs that just been instantiated in our design.
 
ARMadeus-Wishbone IPs that just been instantiated in our design.
  
''button'' and ''led'' are simple slave component we want to
+
''button'' and ''led'' are simple slave component we want to integrate in the FPGA.
integrate in the FPGA.
+
  
 
All these components are connected together with the 'glue logic' component ''intercon''.
 
All these components are connected together with the 'glue logic' component ''intercon''.
  
 
=== Wrapper ===
 
=== Wrapper ===
The [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/firmware/wishbone_example/src/imx9328_wb16_wrapper.vhd?view=markup wrapper] is used to convert i.MX interface signals into Wishbone signals. Table above show signals from i.MX and signals to wishbone conversion :
+
The [http://armadeus.git.sourceforge.net/git/gitweb.cgi?p=armadeus/armadeus;a=blob;f=firmware/wishbone_example/src/wishbone_wrapper.vhd;h=d23110bac06cb121677e551c9eb5efc36b9e5981;hb=HEAD wrapper] is used to convert i.MX interface signals into Wishbone signals.
 
+
{| class="wikitable" align="center" style="text-align:center; width:50%;" border="1"
+
|-
+
! bgcolor=lightgray scope=col | i.MX signals
+
! bgcolor=lightgray scope=col | function
+
! bgcolor=lightgray scope=col | Wishbone signals
+
|-
+
| imx_address(12)
+
| Address vector
+
| wbm_address(13)
+
|-
+
| imx_data(16)
+
| Data vector
+
| wbm_writedata(16) and wbm_readdata(16)
+
|-
+
| imx_cs_n
+
| Chip select
+
| wbm_strobe and wbm_cycle
+
|-
+
| imx_oe_n
+
| Read signal
+
| /wbm_write
+
|-
+
| imx_eb3_n
+
| Write signal
+
| wbm_write
+
|-
+
| -
+
| Acknowledge
+
| wbm_ack
+
|}
+
  
 
=== Intercon ===  
 
=== Intercon ===  
  
The [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/firmware/wishbone_example/src/imx9328_wb16_wrapper00_mwb16_intercon.vhd?view=markup intercon] is a component used to manage signal between wishbone master and slaves component. This component decode Wishbone-master addresses and dispatch its to Wishbone-slave components.
+
The [http://armadeus.git.sourceforge.net/git/gitweb.cgi?p=armadeus/armadeus;a=blob;f=firmware/wishbone_example/src/intercon.vhd;h=dfa98f69ee2263a715945173e138c846e186981c;hb=HEAD intercon] is a component used to manage signals between Wishbone master and slave components. This component decode Wishbone-master addresses and dispatch them to Wishbone-slave components.
  
[[image:Wb_intercon.png|center|frame|'''figure 2''' - ''Intercon internal structure''|500px]]
+
[[image:Wb_intercon.png|center|500px|thumb|'''figure 2''' - ''Intercon internal structure'']]
  
 
== Wishbone slave application components ==
 
== Wishbone slave application components ==
  
In this example their are 3 wishbone-slave components :
+
In this example there are 3 Wishbone-slave components :
  
 
=== irq manager ===
 
=== irq manager ===
  
Some component (here, just button) generate interrupts, [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/firmware/wishbone_example/src/irq_mngr.vhd?view=markup irq manager] is used to
+
Some components (here, only ''button'') generate interrupts, [http://armadeus.git.sourceforge.net/git/gitweb.cgi?p=armadeus/armadeus;a=blob;f=firmware/wishbone_example/src/irq_mngr.vhd;h=014735fb81478b668091beac08af358d6c61240c;hb=HEAD irq manager] is used to mux these interrupts for i.MX. The irq_mngr can manage up to 16 internal interrupts.  
group these interrupts for i.MX. The irq_mngr can manage up to 16 internal
+
interrupts.  
+
  
 
IRQ manager component has tree registers, one to enable interrupts, one for flags/acknowledge interrupts and one identification register :
 
IRQ manager component has tree registers, one to enable interrupts, one for flags/acknowledge interrupts and one identification register :
  
{| class="wikitable" align="center" style="text-align:center; width:30%;" border="1"
+
{| align="center" border="1" cellpadding="5" cellspacing="0" summary="irq_mgr registers"
|-
+
|- style="background:#efefef;" align="center"
! bgcolor=lightgray scope=col | register
+
! register !! function
! bgcolor=lightgray scope=col | function
+
 
|-
 
|-
 
| mask
 
| mask
Line 101: Line 58:
 
|}
 
|}
  
 +
=== wb_led ===
  
=== wb_led ===
+
{{Note| On apf9328_devfull and on apf27_dev a LED is already soldered on fpga. <br> '''For apf27_dev the FPGA bank1 must be powered with 3.3V''' (connect pin 39 and pin 1 on J20 header (near Ethernet one)). For '''apf51Dev''' don't forget to power banks with jumper FPGA_Bank3 and FPGA_Bank1}}
  
This component is a simple 16-bit Wishbone slave output port, from [http://www.opencores.org/projects.cgi/web/wishbone/wbspec_b3.pdf wishbone specification example] (p110).
+
This component is a simple 16-bit Wishbone slave output port, from [http://cdn.opencores.org/downloads/wbspec_b3.pdf wishbone specification example] (p110).
  
[[image:wbs_led.png|center|frame|'''figure 3''' - ''LED internal structure''|600px]]
+
[[image:wbs_led.png|center|thumb|600px|'''figure 3''' - ''LED internal structure'']]
  
 
It is a simple register, that can be read and write. The LED is controlled with register pin 0.
 
It is a simple register, that can be read and write. The LED is controlled with register pin 0.
Line 112: Line 70:
 
The two registers are :
 
The two registers are :
  
{| class="wikitable" align="center" style="text-align:center; width:30%;" border="1"
+
{| align="center" border="1" cellpadding="5" cellspacing="0" summary="wb_led registers"
 +
|- style="background:#efefef;" align="center"
 +
! register name !! (relative) address !! function
 
|-
 
|-
! bgcolor=lightgray scope=col | register
+
| LED || 0x00 || Write '1' in LSB to shutdown LED
! bgcolor=lightgray scope=col | function
+
 
|-
 
|-
| LED
+
| id || 0x02 || read identification number
| Write '1' in LSB to shutdown LED
+
|-
+
| id
+
| read identification number
+
 
|}
 
|}
  
Line 128: Line 83:
 
Wb_button component, is like ''led'' but in read only and with an edge detector to rise irq.
 
Wb_button component, is like ''led'' but in read only and with an edge detector to rise irq.
  
[[image:wbs_button.png|center|frame|'''figure 4''' - ''Button internal structure''|500px]]
+
{{Note| On [[APF27Dev]] and [[APF51Dev]] a button is already soldered to a FPGA pin. Just don't forget to power corresponding FPGA bank.<br> For [[APF9328DevFull]] a button must be connected to IO_L01N_0 FPGA pin (connector X7/FPGA2, pin 1)}}
 +
[[image:wbs_button.png|center|thumb|500px|'''figure 4''' - ''Button internal structure'']]
  
 
The two registers are:
 
The two registers are:
  
{| class="wikitable" align="center" style="text-align:center; width:30%;" border="1"
+
{| align="center" border="1" cellpadding="5" cellspacing="0" summary="wb_button registers"
 +
|- style="background:#efefef;" align="center"
 +
! register !! (relative) address !! function
 
|-
 
|-
! bgcolor=lightgray scope=col | register
+
| id || 0x00 || read identification number
! bgcolor=lightgray scope=col | function
+
 
|-
 
|-
| Button
+
| Button || 0x02 || read LSB to know button state
| read LSB to know button state
+
|-
+
| id
+
| read identification number
+
 
|}
 
|}
  
 
== Components drivers ==
 
== Components drivers ==
  
Each component is drove with a Linux driver described above. All driver code is in armadeus directory in [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/target/linux/modules/fpga/wishbone_example/ target/linux/module/fpga/wishbone_example/].
+
Each component is driven by a Linux driver described above. All driver code is in armadeus directory in [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/target/linux/modules/fpga/wishbone_example/ target/linux/module/fpga/wishbone_example/].
  
Each component has an identification register with unique number. This number is used by driver to unsure that device is present when it modproded.
+
Each component has an identification register with unique number. This number is used by driver when modprobed to unsure that device is present.
  
 
=== irq manager ===
 
=== irq manager ===
  
The description of IRQ management module is available [[POD_Interrupt_handler | here]]. The module code source can be found [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/target/linux/modules/fpga/wishbone_example/wb_irq_mngr/main.c?view=markup  here].
+
The description of IRQ management module is available [[POD_Interrupt_handler | here]]. The module's source code can be found [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/target/linux/modules/fpga/wishbone_example/wb_irq_mngr/main.c?view=markup  here].
  
 
=== LED ===
 
=== LED ===
  
LED driver is seen in linux like a character driver. Writing in dev file will enable or disable LED.
+
LED driver is seen in Linux like a character driver. Writing in a ''/dev'' file will enable or disable the LED.
  
 
The driver is composed of two modules :
 
The driver is composed of two modules :
  
* [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/target/linux/modules/fpga/wishbone_example/wb_led/g_led.c?view=markup g_led] : this module implement generic LED driver mechanisms.
+
* '''led_ocore''' : this module implement generic LED driver mechanisms.
* [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/target/linux/modules/fpga/wishbone_example/wb_led/board_leds.c?view=markup board_led] : This module describe specific datas for each LED-component available in design. These datas are described in structure ''plat_led_port'' and ''plat_led_device''. The module will register each LED with ''platforme_device_register'' function. When a ''plat_led__port'' device is registered, ''g_led'' driver will detect it and will probe it with ''led_probe'' function.
+
* '''wb_example_led''' : This module describe specific datas for each LED-component available in design. These datas are described in structure ''plat_led_port'' and ''plat_led_device''. The module will register each LED with ''platform_device_register()'' function. When a ''plat_led_port'' device is registered, ''led_ocore'' driver will detect it and will probe it with ''led_probe'' function.
  
 
=== button ===
 
=== button ===
Line 167: Line 120:
 
Button driver is seen in Linux like a character driver. When a process want to read value in button register, the driver will block reading until an interrupt occur.
 
Button driver is seen in Linux like a character driver. When a process want to read value in button register, the driver will block reading until an interrupt occur.
  
Structure of button driver is similar to LED driver, it is decomposed in two modules :
+
Structure of button driver is similar to LED driver (two modules) :
  
* [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/target/linux/modules/fpga/wishbone_example/wb_button/gbutton.c?view=markup gbutton] : This module implement generic button driver mechanisms.
+
* '''button_ocore''' : This module implements generic button driver mechanisms.
* [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/target/linux/modules/fpga/wishbone_example/wb_button/board_buttons.c?view=markup board_button] : Like LED module, this module describe specifics datas for each button-component available in design.
+
* '''wb_example_button''' : Like LED module, this module describes specific data for each button-component available in design.
  
 
== Using the design ==
 
== Using the design ==
Line 178: Line 131:
 
=== Make the FPGA bitstream ===
 
=== Make the FPGA bitstream ===
  
ISE Webpack is mandatory to generate the bitstream, then [[ISE_WebPack_installation_on_Linux | its installation is required]]. Once bitstream generated, it can be downloaded in FPGA with [[Target_Software_Installation#FPGA_firmware_installation | U-Boot]] or [[FPGA_loader | Linux]].
+
ISE Webpack is mandatory to generate the bitstream, so [[ISE_WebPack_installation_on_Linux | its installation is required]]. Once bitstream has been generated, it can be downloaded in FPGA with [[Target_Software_Installation#FPGA_firmware_installation | U-Boot]] or [[FPGA_loader | Linux]].
 +
For '''apf51''', bitstream is under the directory '''firmware/wishbone_example/wishbone_example51/binaries/top_wishbone_example51_lx9.bin'''. For apf27 and apf9328 bitstream can be found in '''firmware/wishbone_example/wishbone_example9328_27/bin/'''.
  
 
=== Compile Linux drivers ===
 
=== Compile Linux drivers ===
  
To compile driver for this design select it in ''make linux26-menuconfig'' :
+
To compile the drivers for this design select them in Linux menuconfig:
 +
<pre class="host">
 +
$ make linux-menuconfig
 +
</pre>
  
 
<pre class="config">
 
<pre class="config">
Line 188: Line 145:
 
         Armadeus specific drivers --->
 
         Armadeus specific drivers --->
 
             FPGA Drivers --->
 
             FPGA Drivers --->
                 [*] Drivers for wishbone example  
+
                 [*]   Board designs
                 <M>     Wishbone Button driver
+
                [*]    board drivers for wishbone example
                 <M>     Wishbone LED driver
+
                 <M>       board Button
                 <M>     IRQ manager with wishbone interface
+
                 <M>       board Led
 +
                 <M>       board irq
 
</pre>
 
</pre>
  
Make linux drivers
+
and compile them:
 
<pre class="host">
 
<pre class="host">
make linux26
+
$ make linux && make
 
</pre>
 
</pre>
  
Then Flash [[Target_Software_Installation#Linux_kernel_installation | Linux]] and  [[Target_Software_Installation#rootfs_installation | rootfs]].
+
Then reflash [[Target_Software_Installation#Linux_kernel_installation | Linux]] and  [[Target_Software_Installation#rootfs_installation | rootfs]] images.
  
 
=== Play with button and LED ===
 
=== Play with button and LED ===
  
==== Mount modules ====
+
==== Load modules ====
  
Modules must be mounted in right order with ''modprobe'' command :
+
Modules must be loaded in right order with ''modprobe'' command :
  
 
* IRQ manager :
 
* IRQ manager :
 
<pre class="apf">
 
<pre class="apf">
 
# modprobe irq_ocore
 
# modprobe irq_ocore
 +
# modprobe wb_example_irq_mngr
 
</pre>
 
</pre>
* Button generic module must be mounted before board module:
+
* Button generic module must be loaded before board module:
 
<pre class="apf">
 
<pre class="apf">
# modprobe gbutton
+
# modprobe button_ocore
# modprobe board_buttons
+
# modprobe wb_example_buttons
BUTTON0: MAJOR: 251 MINOR: 0
+
button button.0: BUTTON0: MAJOR: 249 MINOR: 0
button: irq registered : 193
+
BUTTON0 loaded
BUTTON0 insered
+
 
</pre>
 
</pre>
* LED generic module must be mounted before board module:
+
* LED generic module must be loaded before board module:
 
<pre class="apf">
 
<pre class="apf">
# modprobe g_led
+
# modprobe led_ocore
# modprobe board_leds
+
# modprobe wb_example_led
LED0: MAJOR: 252 MINOR: 0
+
LED0: MAJOR: 248 MINOR: 0
 
LED module LED0 insered
 
LED module LED0 insered
 
</pre>
 
</pre>
Line 229: Line 187:
 
==== Device access ====
 
==== Device access ====
  
Devices access are done with special caracters file. These file must be created with major and minor number given when modules are mounted (see ''Mount modules'' above in this page) :
+
Devices access are done with special caracters file. These file must be created '''with major and minor number given when modules are loaded''' (see ''Load modules'' above) :
  
 
* Make LED access :
 
* Make LED access :
 
<pre class="apf">
 
<pre class="apf">
# mknod /dev/led0 c 252 0
+
# mknod /dev/led0 c LED_MAJOR_NUMBER 0
 
</pre>
 
</pre>
 
* Make button access :
 
* Make button access :
 
<pre class="apf">
 
<pre class="apf">
# mknod /dev/button0 c 251 0
+
# mknod /dev/button0 c BUTTON_MAJOR_NUMBER 0
 
</pre>
 
</pre>
 +
 +
Replace '''LED_MAJOR_NUMBER''' and '''BUTTON_MAJOR_NUMBER''' with correct major number given when modprobe is done.
  
 
==== Test LED ====
 
==== Test LED ====
  
A test program is available in [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/target/linux/modules/fpga/wishbone_example/wb_led/testled.c?view=markup module directory], simply compile it with arm-linux-gcc compiler :
+
A test program is available in module directory:
 +
<pre class="host">
 +
target/linux/modules/fpga/board_designs/wishbone_example/wb_led/
 +
</pre>
 +
simply compile it with arm-linux-gcc compiler :
  
 
<pre class="host">
 
<pre class="host">
$ arm-linux-gcc testled.c -o testled
+
$ make test
 
</pre>
 
</pre>
  
Download it in apf, then test it :
+
Download ''testled'' binary on your APF, then test it :
 
<pre class="apf">
 
<pre class="apf">
 
# ./testled /dev/led0  
 
# ./testled /dev/led0  
Line 265: Line 229:
 
==== Test Button ====
 
==== Test Button ====
  
A test program is available in [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/target/linux/modules/fpga/wishbone_example/wb_button/testbutton.c?view=markup module directory], simply compile it with ''arm-linux-gcc'' compiler :
+
A test program is available in directory:
 
+
<pre class="host">
 +
target/linux/modules/fpga/board_designs/wishbone_example/wb_button/
 +
</pre>
 +
simply compile it in the directory with command:
 
<pre class="host">
 
<pre class="host">
$ arm-linux-gcc testbutton.c -o testbutton
+
$ make test
 
</pre>
 
</pre>
  
 +
copy the ''testbutton'' binary in your target then launch it:
 
<pre class="apf">
 
<pre class="apf">
 
# ./testbutton /dev/button0
 
# ./testbutton /dev/button0
Line 286: Line 254:
 
</pre>
 
</pre>
  
Each button push or release activate reading register value.
+
Each time button is pushed or released, button state is printed out.
  
 
==== Switching LED with button ====
 
==== Switching LED with button ====
  
A simple program is available in [http://armadeus.svn.sourceforge.net/viewvc/armadeus/trunk/target/linux/modules/fpga/wishbone_example/push-led.c?view=markup wishbone example directory] to switch on the LED when button is pressed.
+
A simple program is available in wishbone example directory:
 +
<pre class="host">
 +
target/linux/modules/fpga/board_designs/wishbone_example/
 +
</pre>
 +
to switch on the LED when button is pressed.
  
 
To compile :
 
To compile :
 
<pre class="host">
 
<pre class="host">
arm-linux-gcc push-led.c -o push-led
+
$ make test
 
</pre>
 
</pre>
  
To use it, simply type :
+
To use it, simply type (after downloaded it under your target):
  
 
<pre class="apf">
 
<pre class="apf">
Line 304: Line 276:
 
</pre>
 
</pre>
  
Push the button to switch on the LED.
+
Push the button to switch on/off the LED.

Latest revision as of 11:43, 30 June 2022


This article is intended to explain how to design Wishbone compatible components with simple example. The VHDL source code can be found in firmware/wishbone_example from our gitlab repository.

Description of the Wishbone structure for Armadeus APF boards can be found here (in french).

General structure

The main functionality of this component is to allow to switch-on a LED when a button is pressed.

When button is pressed, the component button send interrupt signal to irq_mngr. irq_mngr will toggle a flag and send interruption to i.MX processor. A Linux driver on i.MX will read irq_mngr and acknowledge irq by writing '1' on the corresponding register. And finally, Linux driver will toggle LED value by writing in led register.

figure 1 - Schematics of wishbone example. /!\ Bus signals are wrong for the APF51 because addr and data are multiplexed.

imx_wrapper, syscon and irq_mngr are standards ARMadeus-Wishbone IPs that just been instantiated in our design.

button and led are simple slave component we want to integrate in the FPGA.

All these components are connected together with the 'glue logic' component intercon.

Wrapper

The wrapper is used to convert i.MX interface signals into Wishbone signals.

Intercon

The intercon is a component used to manage signals between Wishbone master and slave components. This component decode Wishbone-master addresses and dispatch them to Wishbone-slave components.

figure 2 - Intercon internal structure

Wishbone slave application components

In this example there are 3 Wishbone-slave components :

irq manager

Some components (here, only button) generate interrupts, irq manager is used to mux these interrupts for i.MX. The irq_mngr can manage up to 16 internal interrupts.

IRQ manager component has tree registers, one to enable interrupts, one for flags/acknowledge interrupts and one identification register :

register function
mask write '1' to allow irq
ack/pend read for pending irq, write to acknowledge irq
id identification register

wb_led

Note Note: On apf9328_devfull and on apf27_dev a LED is already soldered on fpga.
For apf27_dev the FPGA bank1 must be powered with 3.3V (connect pin 39 and pin 1 on J20 header (near Ethernet one)). For apf51Dev don't forget to power banks with jumper FPGA_Bank3 and FPGA_Bank1


This component is a simple 16-bit Wishbone slave output port, from wishbone specification example (p110).

figure 3 - LED internal structure

It is a simple register, that can be read and write. The LED is controlled with register pin 0.

The two registers are :

register name (relative) address function
LED 0x00 Write '1' in LSB to shutdown LED
id 0x02 read identification number

wb_button

Wb_button component, is like led but in read only and with an edge detector to rise irq.

Note Note: On APF27Dev and APF51Dev a button is already soldered to a FPGA pin. Just don't forget to power corresponding FPGA bank.
For APF9328DevFull a button must be connected to IO_L01N_0 FPGA pin (connector X7/FPGA2, pin 1)
figure 4 - Button internal structure

The two registers are:

register (relative) address function
id 0x00 read identification number
Button 0x02 read LSB to know button state

Components drivers

Each component is driven by a Linux driver described above. All driver code is in armadeus directory in target/linux/module/fpga/wishbone_example/.

Each component has an identification register with unique number. This number is used by driver when modprobed to unsure that device is present.

irq manager

The description of IRQ management module is available here. The module's source code can be found here.

LED

LED driver is seen in Linux like a character driver. Writing in a /dev file will enable or disable the LED.

The driver is composed of two modules :

  • led_ocore : this module implement generic LED driver mechanisms.
  • wb_example_led : This module describe specific datas for each LED-component available in design. These datas are described in structure plat_led_port and plat_led_device. The module will register each LED with platform_device_register() function. When a plat_led_port device is registered, led_ocore driver will detect it and will probe it with led_probe function.

button

Button driver is seen in Linux like a character driver. When a process want to read value in button register, the driver will block reading until an interrupt occur.

Structure of button driver is similar to LED driver (two modules) :

  • button_ocore : This module implements generic button driver mechanisms.
  • wb_example_button : Like LED module, this module describes specific data for each button-component available in design.

Using the design

All code for this design is available in ARMadeus tree, firmware (VHDL) and software (Linux drivers).

Make the FPGA bitstream

ISE Webpack is mandatory to generate the bitstream, so its installation is required. Once bitstream has been generated, it can be downloaded in FPGA with U-Boot or Linux. For apf51, bitstream is under the directory firmware/wishbone_example/wishbone_example51/binaries/top_wishbone_example51_lx9.bin. For apf27 and apf9328 bitstream can be found in firmware/wishbone_example/wishbone_example9328_27/bin/.

Compile Linux drivers

To compile the drivers for this design select them in Linux menuconfig:

 $ make linux-menuconfig
    Device Drivers --->
        Armadeus specific drivers --->
            FPGA Drivers --->
                [*]   Board designs
                [*]     board drivers for wishbone example
                <M>       board Button
                <M>       board Led
                <M>       board irq

and compile them:

$ make linux && make

Then reflash Linux and rootfs images.

Play with button and LED

Load modules

Modules must be loaded in right order with modprobe command :

  • IRQ manager :
# modprobe irq_ocore
# modprobe wb_example_irq_mngr
  • Button generic module must be loaded before board module:
# modprobe button_ocore
# modprobe wb_example_buttons
button button.0: BUTTON0: MAJOR: 249 MINOR: 0
BUTTON0 loaded
  • LED generic module must be loaded before board module:
# modprobe led_ocore
# modprobe wb_example_led
LED0: MAJOR: 248 MINOR: 0
LED module LED0 insered

Device access

Devices access are done with special caracters file. These file must be created with major and minor number given when modules are loaded (see Load modules above) :

  • Make LED access :
# mknod /dev/led0 c LED_MAJOR_NUMBER 0
  • Make button access :
# mknod /dev/button0 c BUTTON_MAJOR_NUMBER 0

Replace LED_MAJOR_NUMBER and BUTTON_MAJOR_NUMBER with correct major number given when modprobe is done.

Test LED

A test program is available in module directory:

target/linux/modules/fpga/board_designs/wishbone_example/wb_led/

simply compile it with arm-linux-gcc compiler :

$ make test

Download testled binary on your APF, then test it :

# ./testled /dev/led0 
Testing led driver
Read 1
Write 0
Read 0
Write 1
Read 1
Write 0
Read 0

LED is blinking slowly.

Test Button

A test program is available in directory:

target/linux/modules/fpga/board_designs/wishbone_example/wb_button/

simply compile it in the directory with command:

$ make test

copy the testbutton binary in your target then launch it:

# ./testbutton /dev/button0
Testing button driver
Read 1
Read 0
Read 1
Read 0
Read 1
Read 0
Read 0
Read 1
Read 0
Read 1

Each time button is pushed or released, button state is printed out.

Switching LED with button

A simple program is available in wishbone example directory:

target/linux/modules/fpga/board_designs/wishbone_example/

to switch on the LED when button is pressed.

To compile :

$ make test

To use it, simply type (after downloaded it under your target):

# ./push-led /dev/button0 /dev/led0 
Blink a led pushing button

Push the button to switch on/off the LED.