Edk Libs Ref Guide
Edk Libs Ref Guide
Reference Guide
R
R
"Xilinx" and the Xilinx logo shown above are registered trademarks of Xilinx, Inc. Any rights not expressly granted herein are reserved.
CoolRunner, RocketChips, Rocket IP, Spartan, StateBENCH, StateCAD, Virtex, XACT, XC2064, XC3090, XC4005, and XC5210 are
registered trademarks of Xilinx, Inc.
EDK OS and Libraries Reference Guide www.xilinx.com UG114 (v3.0) June 22, 2004
1-800-255-7778
EDK OS and Libraries Reference Guide
UG114 (v3.0) June 22, 2004
The following table shows the revision history for this document.
Version Revision
01/30/04 1.0 Initial release for EDK 6.2i.
03/12/04 Updated for service pack release.
03/19/04 2.0 Updated for service pack release.
06/22/04 3.0 Updated for service pack release.
UG114 (v3.0) June 22, 2004 www.xilinx.com EDK OS and Libraries Reference Guide
1-800-255-7778
EDK OS and Libraries Reference Guide www.xilinx.com UG114 (v3.0) June 22, 2004
1-800-255-7778
R
Preface
Guide Contents
This book contains the following chapters.
x Chapter 1, “Introduction”
x Chapter 2, “Xilinx Microkernel (XMK)”
x Chapter 3, “LibXil Standard C Libraries”
x Chapter 4, “Standalone Board Support Package”
x Chapter 5, “Xilkernel”
x Chapter 6, “LibXil Net”
x Chapter 7, “LibXil File”
x Chapter 8, “LibXil FATFile System (FATfs)”
x Chapter 9, “LibXil Memory File System (MFS)”
x Chapter 10, “LibXil Profile”
Additional Resources
For additional information, go to http://support.xilinx.com. The following table lists
some of the resources you can access from this website. You can also directly access these
resources using the provided URLs.
Resource Description/URL
EDK Home Embedded Development Kit home page, FAQ and tips.
http://www.xilinx.com/edk
EDK Examples A set of complete EDK examples.
http://www.xilinx.com/ise/embedded/edk_examples.htm
Tutorials Tutorials covering Xilinx design flows, from design entry to
verification and debugging
http://support.xilinx.com/support/techsup/tutorials/index.htm
Answer Browser Database of Xilinx solution records
http://support.xilinx.com/xlnx/xil_ans_browser.jsp
Resource Description/URL
Application Notes Descriptions of device-specific design techniques and approaches
http://support.xilinx.com/apps/appsweb.htm
Data Sheets Device-specific information on Xilinx device characteristics,
including readback, boundary scan, configuration, length count,
and debugging
http://support.xilinx.com/xlnx/xweb/xil_publications_index.jsp
Problem Solvers Interactive tools that allow you to troubleshoot your design issues
http://support.xilinx.com/support/troubleshoot/psolvers.htm
Tech Tips Latest news, design tips, and patch information for the Xilinx
design environment
http://www.support.xilinx.com/xlnx/xil_tt_home.jsp
GNU Manuals The entire set of GNU manuals
http://www.gnu.org/manual
Conventions
This document uses the following conventions. An example illustrates each convention.
Typographical
The following typographical conventions are used in this document:
Conventions
Online Document
The following conventions are used in this document:
Chapter 1: Introduction
Chapter 5: Xilkernel
Overview . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Key Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 37
Xilkernel Blocks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 38
Xilkernel Modes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Building Xilkernel Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 39
Xilkernel Process Model. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 41
Xilkernel Scheduling Model. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 42
Xilkernel API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Process Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
Thread Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 45
Semaphores . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 50
Message Queues . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 55
Shared Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59
Mutex Locks . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
Dynamic Block Memory Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65
Interrupt Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 66
Kernel Customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 70
Customizing STDIN and STDOUT . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Customizing User Initialization Routine . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
Customizing Process Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 72
Customizing Scheduling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
Customizing Thread Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
Customizing Semaphore . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Customizing Message Queue . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Customizing Shared Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
Customizing Pthread Mutex . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Customizing Dynamic Block Memory Management . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
Customizing Linker Script (PPC405) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
Configuring System Timer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Configuring Interrupt Handling . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Configuring Debug Messages . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
Copy Kernel Source Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Debugging Xilkernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Memory Footprint . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 78
Xilkernel File Organization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
System Initialization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
Future Enhancements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
Modifying Xilkernel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
User Guide. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80
Quick Glance. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
Protocols Supported . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Library Architecture . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
Protocol Function Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Media Access Layer (MAC) Drivers Wrapper. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
Ethernet Drivers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
ARP (RFC 826) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
IP (RFC 791) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
ICMP (RFC 792) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
UDP (RFC 768) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 87
TCP (RFC 793) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
Sockets API . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
Buffer Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
Current Restrictions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
Functions of LibXilNet . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 88
LibGen Customization . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
Using XilNet in Application . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 100
Features . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123
Profiling Model . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
Customizing xilprofile . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124
Building Applications . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
124
Application Memory Requirements . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
Generating GPROF Files . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
XilProfile Code Description . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
Limitations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
Chapter 1
Introduction
This book describes the software packages that are provided by the Embedded
Development Kit. EDK supplies libraries, board support packages, and complete
operating systems, in addition to the drivers for the peripherals, to help the user develop a
software platform. The following is the distribution of the software packages available for
the user to include in his platform:
x Xilinx Micro-Kernel (XMK) - XMK is the entity representing the collective software
system formed by the following components,
i Standard C Libraries (libc, libm)
i Xilkernel - An embedded kernel
i Standalone Board Support Package (BSP)
i LibXil Net - A networking library
i LibXil MFS - A Memory File System
i LibXil File - A file I/O library
i LibXil Drivers - Device drivers for supported peripherals
x VxWorks Operating System
The software platform can be defined using XPS’s Software Platform Settings dialog box.
Figure 1-1 shows a snapshot of the dialog box. In this example, the user is choosing the
Xilnet and Xilfile libraries, along with the Xilkernel operating system.
This guide documents the Xilinx Micro-kernel, its constituent libraries and the Standalone
board-support package. Documentation for the other operating systems can be found in
their respective reference guides. Device drivers are documented along with the
corresponding peripheral’s documentation.
Chapter 1: Introduction
Chapter 2
Overview
There are three distinct software entities in XMK, with which user applications can
interface - Standard C and Math libraries, LibXil libraries and Xilkernel or Standalone
operating systems.
The Standard C support library consists of the newlib libc, which contains the standard C
functions such as stdio, stdlib and string routines. The math library is an enhancement over
the newlib math library libm and provides the standard math routines.
The LibXil libraries consist of,
x LibXil Driver - Xilinx device drivers
x LibXil Net - Xilinx networking support
x LibXil File - Xilinx file I/O functions
x LibXil MFS - Xilinx memory file system
x LibXil Profile - Xilinx profiling support
The Xilinx Standalone Board Support Package (BSP) and Xilkernel are the two operating
system choices that are provided, in XMK, that can be included in the user application’s
software platform.
Most of the routines in the library are written in C and can be ported to any platform. The
Library Generator (LibGen) configures the libraries for an embedded processor, using the
attributes defined in the Microprocessor Software Specification (MSS) file.
XMK Organization
The structure of XMK is outlined in Figure 2-1. As shown in the figure, the user application
can interface with the XMK components in a variety of ways. The libraries are independent
of each other, except for a few interactions and dependencies between each other. For
example, Xilkernel internally uses the standalone BSP and LibXil File can optionally work
with the LibXil MFS. The LibXil Drivers and the standalone BSP form the lowermost
hardware abstraction layer. All the library and OS components of XMK rely on standard C
library components. The math library, libm.a is also available for linking with the user
applications. Users can mix and match the component libraries, but there may be some
restrictions and implications. This will be described in the reference guides of each
component.
User Application
libc
stdio
stdlib
LibXil string
Xil Kernel LibXil Net LibXil File LibXil Mfs
Profile
Other
libm
Hardware X10143
The Standalone Board Support Package (BSP) is a bare-bones kernel. It provides a very thin
interface to the hardware, offering minimal functionality that will be required by
applications. Some typical functions offered by the standalone BSP include setting up the
interrupt system, exception system, configuring caches and other hardware specific
functions. Certain standalone board support files such as the crt0.S, boot.S and eabi.S are
required for the powerpc processor. These files are provided in the EDK. For a detailed
description, refer to Chapter 4, “Standalone Board Support Package.”
LibXil Driver refers to the device drivers that are included in the software platform to
provide an interface to the peripherals in the system. These drivers are provided along
with EDK and are configured by libgen. This book contains a chapter that briefly discusses
the concept of device drivers and the way they fit in with the software platform, in EDK.
Refer to the “Device Drivers Programmer Guide” chapter in the Processor IP Reference Guide
for this documentation. Device Drivers are documented in further detail, with information
about functionality, interface, configuration and headers file information, in the Xilinx
Device Drivers Reference Guide.
Xilkernel (1) is a simple embedded processor kernel, which can be customized to a great
degree for a given system. Xilkernel has the key features of an embedded kernel like multi-
tasking, priority-driven preemptive scheduling, inter-process communication,
synchronization facilities, interrupt handling etc. It is small, modular, user customizable
and can be used in different system configurations. It is different from the other libraries,
(as indicated in Figure 2-1 in that, it can be in a separate executable file from the user
application. The user application can dynamically link with Xilkernel through a system
call interface. Applications can also statically link with Xilkernel, in a different mode, and
form a single executable. Complete details are available in Chapter 5, “Xilkernel.”
LibXil Net provides networking support using a simple TCP/IP stack based library, which
can be used for network related projects. For complete details, refer to Chapter 6, “LibXil
Net.”
1. Previous EDK releases supported the library version of Xilkernel, which is now deprecated. Refer to Chapter
5, “Xilkernel” for documentation on LibXilkernel.
XMK Organization
LibXil File provides stream based file system and device access through interfaces such as
open, close, read and write. The standard newlib libc contains dummy functions for most
of the operating system specific function calls such as open, close, read, write. These
routines are included in the libgloss component of the standard libc library. The LibXil File
module contains routines to overwrite these dummy functions. The routines interact with
file systems such as Xilinx Memory File System and peripheral devices such as UART,
UARTLITE and GPIO. For complete details refer to Chapter 7, “LibXil File.”
LibXil MFS provides a simple memory based file system, which allows easy access to data
using file based input-output. This system can be easily configured to meet project
requirements by changing the source provided in the installation area. This module is
discussed in detail in Chapter 9, “LibXil Memory File System (MFS).”
LibXil Profile provides a mechanism to perform call-graph and histogram profiling and
produces the profile data in a format that can be analyzed using GNU gprof. For details
refer to Chapter 10, “LibXil Profile.”
User applications will need to include appropriate headers and link with required libraries
for proper compilation and inclusion of required functionality. These libraries and their
corresponding include files are created in the processor’s lib and include directories,
under the current project, respectively. The -I and -L options of the compiler being used
should be leveraged to add these directories to the search paths. Libgen is used to tailor the
compilation of each software component described above. Refer to the chapters on Libgen
and Microprocessor Software Specification in the Embedded Systems Tools Reference Guide
for more information.
Chapter 3
Overview
The Embedded Processor Design Kit (EDK) libraries and device drivers provide standard
C library functions, as well as functions to access peripherals. The EDK libraries are
automatically configured by libgen for every project based upon the Microprocessor
Software Specification file. These libraries and include files are saved in the current
project’s lib and include directories respectively. The -I and -L options of mb-gcc should
be used to add these directories to its library search paths.
Input/Output Functions
The EDK libraries contains standard C functions for I/O, such as printf and scanf. These
are large and may not be suitable for embedded processors. In addition, the EDK
processors (MicroBlaze and PowerPC405) library provides the following smaller I/O
functions:
void print (char *)
This function prints a string to the peripheral designated as standard output in the MSS
file. This function outputs the passed string as is and there is no interpretation of the string
passed. For example, a “\n” passed is interpreted as a new line character and not as a
carriage return and a new line as is the case with ANSI C printf function.
void putnum (int)
This function converts an integer to a hexadecimal string and prints it to the peripheral
designated as standard output in the MSS file.
void xil_printf (const *char ctrl1, ...)
This function is similar to printf but much smaller in size (only 1KB). It does not have
support for floating point numbers. xil_printf also does not support printing of long long
(i.e 64 bit numbers).
The prototypes for these functions are in stdio.h.
Please refer to the “Microprocessor Software Specification (MSS)” chapter in the Embedded
System Tools Guide for information on setting the standard input and standard output
devices for a system.
MicroBlaze Processor
Memory management routines such as malloc, calloc and free can run the gamut of
high functionality (with associated large size) to low functionality (and small size). By
default, the MicroBlaze processor library only supports a simple, small malloc, and a
dummy free. Hence when memory is allocated using malloc, this memory cannot be
reused.
In addition to the simple version, we have now extended the standalone BSP to include
xil_malloc, xil_free and xil_calloc function. In the Standalone OS block, if the
PARAMETER need_xil_malloc is set to TRUE, calls to malloc result in a call to
xil_malloc and the same for free and calloc. These functions are a lighter version of the
newlib based malloc and free, but have the same functionality.
The _STACK_SIZE option to mb-gcc specifies the total memory allocated to stack and
heap. The stack is used for function calls, register saves, and local variables. All calls to
malloc allocate memory from heap. The stack pointer initially points to the bottom (high
end) of memory, and grows toward low memory; the heap pointer starts at low memory
and grows toward high memory. The size of the heap cannot be increased at runtime. The
return value of malloc must always be checked to ensure that it could actually allocate the
memory requested.
Please note that whereas malloc checks that the memory it allocates does not overwrite
the current stack pointer, updates to the stack pointer do not check if the heap is being
overwritten.
Increasing the _STACK_SIZE may be one way to solve unexpected program behavior. Refer
to “Linker Options” in the “GNU Compiler Tools” chapter of the Embedded System Tools Guide
for more information on increasing the stack size.
Arithmetic Operations
MicroBlaze Processor
Integer Arithmetic
Integer addition and subtraction operations are provided in hardware. By default, integer
multiplication is done in software using the library function mulsi3_proc. Integer
multiplication is done in hardware if the mb-gcc option -mno-xl-soft-mul is specified.
Integer divide and mod operations are done in software using the library functions
divsi3_proc and modsi3_proc. MicroBlaze processor can also be customized to use a
hard divider, in which case the div instruction is used in place of the divsi3_proc library
routine.
Double precision multiplication, division and mod functions are carried out by the library
functions muldi3_proc, divdi3_proc and moddi3_proc respectively.
Chapter 4
MicroBlaze BSP
When the user system contains a MicroBlaze processor and no Operating System, the
Library Generator automatically builds the standalone BSP in the project library libxil.a.
Interrupt Handling
The microblaze_enable_interrupts.s and
microblaze_disable_interrupts.s files contain functions to enable and disable
interrupts on the MicroBlaze.
void microblaze_enable_interrupts(void)
This function enables interrupts on the MicroBlaze. When the MicroBlaze starts up,
interrupts are disabled. Interrupts must be explicitly turned on using this function.
void microblaze_disable_interrupts(void)
This function disables interrupts on the MicroBlaze. This function may be called when
entering a critical section of code where a context switch is undesirable.
void microblaze_enable_icache(void)
This functions enables the instruction cache on MicroBlaze. When MicroBlaze starts up, the
instruction cache is disabled. The ICache must be explicitly turned on using this function.
void microblaze_disable_icache(void)
This function disables the instruction cache on MicroBlaze.
void microblaze_enable_dcache(void)
This functions enables the data cache on MicroBlaze. When MicroBlaze starts up, the data
cache is disabled. The Dcache must be explicitly turned on using this function.
void microblaze_disable_dcache(void)
This function disables the instruction cache on MicroBlaze.
MicroBlaze BSP
microblaze_bread_datafsl(val, id)
This macro performs a blocking data get function on an input FSL of MicroBlaze. id is the
FSL identifier and can range from 0 to 7.
microblaze_bwrite_datafsl(val, id)
This macro performs a blocking data put function on an output FSL of MicroBlaze. id is the
FSL identifier and can range from 0 to 7.
microblaze_nbread_datafsl(val, id)
This macro performs a non-blocking data get function on an input FSL of MicroBlaze. id is
the FSL identifier and can range from 0 to 7.
microblaze_nbwrite_datafsl(val, id)
This macro performs a non- blocking data put function on an output FSL of MicroBlaze. id
is the FSL identifier and can range from 0 to 7.
microblaze_bread_cntlfsl(val, id)
This macro performs a blocking control get function on an input FSL of MicroBlaze. id is
the FSL identifier and can range from 0 to 7.
microblaze_bwrite_cntlfsl(val, id)
This macro performs a blocking control put function on an output FSL of MicroBlaze. id is
the FSL identifier and can range from 0 to 7.
microblaze_nbread_cntlfsl(val, id)
This macro performs a non-blocking control get function on an input FSL of MicroBlaze. id
is the FSL identifier and can range from 0 to 7.
microblaze_nbwrite_cntlfsl(val, id)
This macro performs a non-blocking data control function on an output FSL of MicroBlaze.
id is the FSL identifier and can range from 0 to 7.
PowerPC BSP
When the user system contains a PowerPC, and no Operating System, the Library
Generator automatically builds the Stand-Alone BSP in the project library libxil.a.
The Stand-Alone BSP contains boot code, cache, file and memory management,
configuration, exception handling, time and processor specific include functions.
Boot Code
The boot.S, crt0.S, and eabi.S files contain a minimal set of code for initializing the
processor and starting an application.
boot.S
Code in the boot.S consists of the two sections boot and boot0. The boot section
contains only one instruction that is labeled with _boot. During the link process, this
instruction is mapped to the reset vector and the _boot label marks the application’s entry
point. The boot instruction is a jump to the _boot0 label. The _boot0 label must reside
within a ±23-bit address space of the _boot label. It is defined in the boot0 section. The
code in the boot0 section calculates the 32-bit address of the _start label and jumps to it.
crt0.S
Code in the crt0.S file starts executing at the _start label. It initializes the .sbss and
.bss sections to zero, as required by the ANSI C specification, sets up the stack, initializes
some processor registers, and calls the main() function.
The program remains in an endless loop on return from main().
eabi.S
When an application is compiled and linked with the -msdata=eabi option, GCC inserts a
call to the __eabi label at the beginning of the main() function. This is the place where
register R13 must be set to point to the .sdata and .sbss data sections and register R2
must be set to point to the .sdata2 read-only data section.
Code in eabi.S sets these two registers to the correct values. The _SDA_BASE_ and
_SDA2_BASE_ labels are generated by the linker.
Cache
The xcache_l.c file and corresponding xcache_l.h include file provide access to
cache and cache-related operations.
PowerPC BSP
void XCache_DisableDCache(void);
The XCache_DisableDCache() function disables the data cache for all memory regions.
void XCache_DisableICache(void);
The XCache_DisableICache() function disables the instruction cache for all memory
regions.
void XCache_InvalidateICache(void);
The XCache_InvalidateICache() function invalidates the whole instruction cache.
Subsequent instructions produce cache misses and cache line refills.
Exception Handling
This section documents the exception handling API that is provided in the Board Support
Package. For an in-depth explanation on how exceptions and interrupts work on the
PPC405, please refer to the chapter “Exceptions and Interrupts” in the PPC User’s Manual.
The exception handling API consists of a set of the files xvectors.S, xexception_l.c,
and the corresponding header file xexception_l.h.
void XExc_Init(void);
This function sets up the interrupt vector table and registers a “do nothing” function for
each exception. This function has no parameters and does not return a value.
This function must be called before registering any exception handlers or enabling any
interrupts. When using the exception handler API, this function should be called at the
beginning of your main() routine.
IMPORTANT: If you are not using the default linker script, you need to reserve memory
space for storing the vector table in your linker script. The memory space must begin on a
64k boundary. The linker script entry should look like this example:
.vectors :
{
. = ALIGN(64k);
*(.vectors)
}
For further information on linker scripts, please refer to the Linker documentation.
PowerPC BSP
The function provided as the Handler parameter must have the following function
prototype:
Files
File support is limited to the stdin and stdout streams. In such an environment, the
following functions do not make much sense:
x open() (in open.c)
x close() (in close.c)
x fstat() (in fstat.c)
x unlink() (in unlink.c)
x lseek() (in lseek.c)
These files are included for completeness and because they are referenced by the C library.
PowerPC BSP
Memory Management
char *sbrk(int nbytes);
The sbrk() function in the sbrk.c file allocates nbytes of heap and returns a pointer to
that piece of memory. This function is called from the memory allocation functions of the C
library.
Process
The functions getpid() in getpid.c and kill() in kill.c are included for completeness
and because they are referenced by the C library.
Time
The xtime_l.c file and corresponding xtime_l.h include file provide access to the 64-
bit time base counter inside the PowerPC core. The counter increases by one at every
processor cycle.
The sleep.c file and corresponding sleep.h include file implement functions for tired
programs. All sleep functions are implemented as busy loops.
position of the Bitmask parameter clears the corresponding bit in the TSR. This function
does not return a value.
The header file xreg405.h defines the following values for the Bitmask parameter:
Example:
XTime_TSRClearStatusBits(TSR_CLEAR_ALL);
Example:
XTime_PITSetInterval(0x00ffffff);
void XTime_PITEnableInterrupt(void);
The XTime_PITEnableInterrupt() function in xtime_l.c enables the generation of PIT
interrupts. An interrupt occurs when the PIT register contains a value of 1, and is then
decremented. This function does not return a value. XExc_Init() must be called, the PIT
interrupt handler must be registered, and exceptions must be enabled before calling this
function.
PowerPC BSP
Example:
XTime_PITEnableInterrupt();
void XTime_PITDisableInterrupt(void);
The XTime_PITDisableInterrupt() function in xtime_l.c disables the generation of PIT
interrupts. It does not return a value.
Example:
XTime_PITDisableInterrupt();
void XTime_PITEnableAutoReload(void);
The XTime_PITEnableAutoReload() function in xtime_l.c enables the auto-reload
function of the PIT Register. When auto-reload is enabled the PIT Register is automatically
reloaded with the last value loaded by calling the XTime_PITSetInterval function when
the PIT Register contains a value of 1 and is decremented. When auto-reload is enabled, the
PIT Register never contains a value of 0. This function does not return a value.
Example:
XTime_PITEnableAutoReload();
void XTime_PITDisableAutoReload(void);
The XTime_PITDisableAutoReload() function in xtime_l.c disables the auto-reload
feature of the PIT Register. When auto-reload is disabled the PIT decrements from 1 to 0. If
it contains a value of 0 it stops decrementing until it is loaded with a non-zero value. This
function does not return a value.
Example:
XTime_PITDisableAutoReload();
void XTime_PITClearInterrupt(void);
The XTime_PITClearInterrupt() function in xtime_l.c is used to clear
PIT-Interrupt-Status bit in the Timer-Status Register. This bit
specifies whether a PIT interrupt occurred. You must call this function
in your interrupt-handler to clear the Status bit, otherwise another PIT
interrupt will occur immediately after exiting the interrupt –handler
function. This function does not return a value. Calling this function
is equivalent to calling
XTime_TSRClearStatusBits(XREG_TSR_PIT_INTERRUPT_STATUS).
Example:
XTime_PITClearInterrupt();
Chapter 5
Xilkernel
This chapter describes Xilkernel, a kernel for the Xilinx embedded processors. The chapter
contains the following sections.
x “Overview”
x “Key Features”
x “Xilkernel Blocks”
x “Xilkernel Modes”
x “Building Xilkernel Applications”
x “Xilkernel Process Model”
x “Xilkernel Scheduling Model”
x “Xilkernel API”
x “Interrupt Handling”
x “Kernel Customization”
x “Debugging Xilkernel”
x “Memory Footprint”
x “Xilkernel File Organization”
x “System Initialization”
x “Limitations”
x “Future Enhancements”
x “Modifying Xilkernel”
x “User Guide”
Overview
Xilkernel is a small, robust and modular kernel that allows a very high degree of
customization, letting users tailor the kernel to an optimal level both in terms of size and
functionality. It supports the core features required in an embedded/real-time kernel, with
a POSIX API. Xilkernel works on both the MicroBlaze and PowerPC processors. Xilkernel
IPC services can be used to implement higher level services like networking, video, audio
and subsequently, run applications using these services.
Key Features
Xilkernel has the following notable features:
x An API closely supporting a subset of POSIX that targets embedded kernels.
Chapter 5: Xilkernel
Xilkernel Blocks
The kernel is highly modular in design. The user can select and customize the kernel
modules that are needed for the application at hand. Customizing the kernel is discussed
in detail in the “Kernel Customization” section (1). Figure 5-1 shows the various modules of
Xilkernel.
Xilkernel Modules
User Application
User Interrupts
Eg. Webserver
Xilkernel
Thread Process
Semaphores
Management Management
X10131
1. Some of these features might not be fully supported in a given release of xilkernel
Xilkernel Modes
Xilkernel Modes
Xilkernel and user applications can be built in two different modes:
x Separate Executable mode
In this mode, the user applications and kernel can be built as separate executables.
Application entry points can be specified as addresses in the MSS process/pthreads
configuration, using the parameters separate_exec_process_table and
separate_exec_pthread_table in libgen configuration. Applications can get services
from the kernel using the system call interface. These system call wrappers can be
obtained by linking the application with libsyscall.a.This mode provides the flexibility
of developing and dynamically loading each application separately. The stack for the
user application will have to be separately setup as a part of each elf file and the kernel
does no special stack setup. xilkernel.elf is generated only if the process contexts are not
configured in the next mode in the OS specification.
x Kernel Bundled Executable mode
In this mode, the user applications and kernel are bundled and built together as a
single executable elf file. The entry point for an application is a function name that is
specified using parameters kernel_bundled_process_table and
kernel_bundled_pthread_table in the MSS. Building xilkernel using libgen generates
libxilkernel.a library. This can be linked with all the user applications which need to run
on xilkernel, to generate a single kernel bundled executable. Since all the user
applications are part of a single executable, symbol names, such as global variables
and function names, should be unique. Though user applications can directly call the
sys_ prefixed system calls, they would have to lock and unlock the kernel before
calling the system calls. To simplify this process, applications in single executable
mode have access to a thin library layer of system call wrappers that lock the kernel,
execute the system call and then unlock the kernel. Stack is setup by the kernel on
behalf of the single elf applications.The kernel bundled executable mode is a superset of
the separate executable mode. Applications that are separate executables can still
interface with the single executable kernel image dynamically, using the system call
API in libsyscall.a. These system calls will be handled by the system call handlers that
are present in the kernel image.Building and linking applications in the two xilkernel
modes is illustrated in Figure 5-2.
Chapter 5: Xilkernel
Kernel Sources
libsyscall.a libxilkernel.a
xilkernel.elf
+ libsyscall.a Executable
Kernel Bundled
Kernel and Application Application
.elf files X10129
The system call interface for both these xilkernel modes are illustrated in Figure 5-3.
Applications that are a part of the kernel image have the advantage of relatively smaller
system call latency as compared to those in separate executable mode, which requires
another layer of indirection in the system call handler level.
Pure Separate Executable Mode Scenario Kernel Bundled Executable Mode Scenario
System Call
Wrappers
Proc2
xilkernel.elf libxilkernel.a
Proc3
Kernel Image
Kernel Image
X10128
Debugging applications in the two modes is different. See the “Debugging Xilkernel”
section for more details about debugging the applications and the kernel.
Chapter 5: Xilkernel
process, the initialized sections will be invalid, unless some external mechanism is used to reload the
elf image before creating the process.
Active
0 A
1
B C D
2
(Blocked)
Priority
13 E
14 F
G
15
(Blocked)
X10132
Xilkernel API
Activated Terminated
in
led
Blo
du
cke
he
d
Sc
t
ou
ted
Un
led
ina
blo
du
rm
c
he
ke
Te
Sc
d
PROC_READY PROC_WAIT
ed
at
in
rm
Unblocked
Te
X10130
Xilkernel API
Process Management
A process is created and handled using the following interfaces.Some of the functions are
optional and can be configured in during system initialization. Refer to the “Customizing
Process Management” section for more details. Currently, a specific process_exit call is
required at the end of the process’s code to allow the operating system to reclaim the
process’s resources.
Chapter 5: Xilkernel
Parameters None
Returns None
Description Removes the process from the system. Schedules the next process
in the system.
Caution! Do not use this to terminate a thread (described later on).
Includes sys/process.h
Parameters None
Returns None
Description Yields the processor to the next process or thread.The current
process goes to PROC_READY state and is put at the end of the
ready queue.
Note This function is optionally configured using
CONFIG_PROCESS_YIELD.
Includes sys/process.h
Xilkernel API
Parameters None
Returns Priority of the current process.
Description Gets the priority of the current process or thread.
Includes sys/process.h
Parameters None
Returns Process ID of current process or thread.
Description Gets the Process ID of process context that is executing currently.
Includes sys/process.h
Thread Management
Xilkernel supports the basic POSIX threads API. A thread is scheduled and allocated in the
same way as a process. Threads created in the system have a kernel wrapper to which they
return control to when they terminate. Therefore a specific exit function is not required at
the end of the thread’s code. Thread stack is allocated on the thread’s behalf from a pool of
bss memory that is statically allocated depending on the maximum number of threads in
the system. Therefore, threads created dynamically are not required to be associated with
an elf file. The entire thread module is optional and can be configured in or out as a part of
the software specification. See the “Customizing Thread Management” section for more
Chapter 5: Xilkernel
Includes pthread.h
Xilkernel API
Parameters None
Returns On success, returns thread identifier of current thread.
Error behavior not defined.
Description The pthread_self() function returns the thread ID of the calling
thread.
Includes pthread.h
Chapter 5: Xilkernel
Xilkernel API
Chapter 5: Xilkernel
Semaphores
Xilkernel supports kernel allocated POSIX semaphores that can be used for
synchronization. POSIX semaphores are counting semaphores that also count below zero
(a negative value indicates the number of processes blocked on the semaphore). Xilkernel
also supports a few interfaces for working with named semaphores. The number of
semaphores allocated in the kernel and the length of semaphore wait queues can be
configured during system initialization. Refer to the “Customizing Semaphore” section for
more details.The semaphore module is optional and can be configured in or out during
system initialization. The message queue module, described later on in this document,
uses semaphores. Therefore this module needs to be included if message queues are to be
used. The Xilkernel semaphore interface is described below.
Xilkernel API
Chapter 5: Xilkernel
Includes semaphore.h
Xilkernel API
Includes semaphore.h
Chapter 5: Xilkernel
Xilkernel API
Includes semaphore.h
Message Queues
Xilkernel supports kernel allocated XSI message queues. XSI is the X/Open System
Interface which is a set of optional interfaces under POSIX. Message queues can be used as
an IPC mechanism. The message queues can take in arbitrary sized messages. However,
buffer memory allocation must be configured appropriately for the memory blocks
required for the messages, as a part of system malloc initialization.The number of message
queue structures allocated in the kernel and the length of the message queues can be also
be configured during system initialization. The message queue module is optional and can
be configured in/out. Refer to the “Customizing Message Queue” section for more details.
This module depends on the semaphore module and the dynamic block memory
Chapter 5: Xilkernel
allocation module being present in the system. The Xilkernel message queue interface is
described below.
Includes sys/msg.h
sys/ipc.h
Xilkernel API
Chapter 5: Xilkernel
int msgsnd (int msqid, const void *msgp, size_t msgsz, int msgflg)
Xilkernel API
ssize_t msgrcv (int msqid, void *msgp, size_t nbytes, long msgtyp, int
msgflg
Includes sys/msg.h
sys/ipc.h
Shared Memory
Xilkernel supports kernel allocated XSI shared memory. XSI is the X/Open System
Interface which is a set of optional interfaces under POSIX. Shared memory is a common,
low-latency IPC mechanism. Shared memory blocks required during run-time must be
identified and specified during the system configuration.From this specification, buffer
memory is allocated to each shared memory region. Shared memory is currently not
allocated dynamically at run-time. This module is optional and can be configured in or out
during system specification. Refer to the “Customizing Shared Memory” section for more
details. The Xilkernel shared memory interface is described below.
Chapter 5: Xilkernel
Caution! The memory buffers allocated by the shared memory API might not be aligned at
word boundaries. Therefore, structures should not be arbitrarily mapped to shared memory
segments, without checking if alignment requirements are met.
Includes sys/shm.h
sys/ipc.h
Xilkernel API
Chapter 5: Xilkernel
Mutex Locks
Xilkernel provides support for kernel allocated POSIX thread mutex locks. This
synchronization mechanism can be used alongside of the pthread_ API. The number of
mutex locks and the length of the mutex lock wait queue can be configured during system
Xilkernel API
specification. This module is also optional and can be configured in or out during system
specification. Please refer to the “Customizing Shared Memory”section for more details.
Parameters mutex is the location where the newly created mutex lock’s
identifier is to be stored.
attr is the mutex creation attributes structure.
Returns Returns 0 on success and mutex identifier in *mutex.
Returns EAGAIN if system out of resources.
Description The pthread_mutex_init() function initializes the mutex referenced
by mutex with attributes specified by attr. If attr is NULL, the
default mutex attributes are used; the effect shall be the same as
passing the address of a default mutex attributes object. Upon
successful initialization, the state of the mutex becomes initialized
and unlocked. Only mutex itself may be used for performing
synchronization. The result of referring to copies of mutex in calls
to pthread_mutex_lock(), pthread_mutex_trylock(),
pthread_mutex_unlock(), and pthread_mutex_destroy() is undefined.
Attempting to initialize an already initialized mutex results in
undefined behavior.In cases where default mutex attributes are
appropriate, the macro PTHREAD_MUTEX_INITIALIZER can be
used to initialize mutexes that are statically allocated. The effect
shall be equivalent to dynamic initialization by a call to
pthread_mutex_init() with parameter attr specified as NULL,
except that no error checks are performed.
For example,
static pthread_mutex_t foo_mutex =
PTHREAD_MUTEX_INITIALIZER;
Note: The mutex locks allocated by xilkernel follow the semantics of
PTHREAD_MUTEX_DEFAULT mutex locks. i.e attempting to recursively
lock the mutex results in undefined behavior. Attempting to unlock the
mutex if it was not locked by the calling thread results in undefined
behavior. Attempting to unlock the mutex if it is not locked results in
undefined behavior.
Includes pthread.h
Chapter 5: Xilkernel
Includes pthread.h
Xilkernel API
Includes pthread.h
Chapter 5: Xilkernel
allocating memory. The following are the block memory allocation interfaces. This module
is optional and can be included during system initialization.
Caution! The memory buffers allocated by the block memory allocation API might not be
aligned at word boundaries. Therefore, structures should not be arbitrarily mapped to memory
allocated this way, without checking if alignment requirements are ment.
Interrupt Handling
Xilkernel abstracts away the basic interrupt handling requirements of the kernel during
initialization. Even though the kernel will be functional without any interrupts, it makes
sense for the system to be at least driven by a single timer pulse for scheduling. In this case
the kernel handles the main timer interrupt, using it as the kernel tick to perform
scheduling. The timer interrupt is initialized and tied to the vectoring code during system
initialization. For MicroBlaze xilkernels, the system specification requires that a timer
device specification is present. MicroBlaze systems must use either the standard Xilinx FIT
or PIT timers. The timer tick interval can be customized by the user based on the
Interrupt Handling
application if the PIT is used in MicroBlaze systems and always, in PPC405 systems. Refer
to the “Configuring System Timer” section for more details.
Interrupts/
Exceptions
Enabled
Task Code
Interrupted
Next Task
Proceeds X10141
The interrupt service in this scenario with a single timer interrupt in the system is sketched
in Figure 5-6. Upon an interrupt, the volatile registers (defined by the EABI of the
processor) are saved onto the interrupted task’s stack. The interrupt is then vectored to a
handler that is registered at system startup. In Xilkernel’s case, the timer_int_handler()
routine, is the registered handler. This routine invokes process_scheduler() to request a
rescheduling operation. If the reschedule operation switched tasks, a context switch is
performed. If a programmable interval timer is present in the system (always present in
PPC) then its counter is reset to the interval defined at system startup. After the context
switch, execution will resume in the context of the switched-to process. Since volatile
registers were saved on the stack during an interrupt, they are again restored
appropriately from the stack of whatever process gets to execute.
Xilkernel can also work with multiple interrupts in the system, handled through an
interrupt controller. See the “Configuring Interrupt Handling” section for more details on
configuring Xilkernel for multiple external interrupt handling. Figure 5-7 illustrates the
service sequence when interrupts are handled through an interrupt controller. The
interrupt controller’s handler services all interrupt requests. However, the
timer_int_handler() does not immediately perform a context switch, in this configuration. It
sets a flag indicating if a context switch is required. The interrupt controller’s handler
recognizes a pending context switch and performs the actual context switch at the end of
the service routine. The rest of the flow is similar to the basic service routine. The flow is
slightly different from PPC systems, since there is a dedicated interrupt notification for the
internal PIT device. In other words, the handlers for the system timer interrupt and other
external interrupts are different and hence the interrupt controller’s handler follows this
Chapter 5: Xilkernel
sequence of actions, without the scheduling portion, while the timer_int_handler() performs
the same sequence of actions as the basic service routine.
IE = 1
Task Code
Gets
Interrupted
_ _interrupt_handler( )
IE = 0 save volatile registers
intc_device_interrupt_handler( ); intc_device_interrupt_handler( )
1. Determine source of interrupts
2. Service ALL interrupt requests
3. IF process_scheduler( ) invoked on
a timer interrupt THEN
Do a context switch if required
IE = 1
X10140
There are certain limitations on the operations that can be performed inside the user-level
interrupt handlers. Since, technically, the system is still executing the ISR in the context of
the task that was interrupted, invoking any kind of API that may cause a rescheduling
operation can potentially cause the system to enter an invalid state. The advantage of
letting the system still be in the context of the process that was interrupted, in an ISR, is
that on an interrupt, the entire context of the process need not be saved. This can provide
significant reduction in the actual interrupt service response time. However, it imposes the
restriction described above. The actual context switch, due to a rescheduling operation by
the kernel, occurs at the end of servicing all the ISRs.
Xilkernel support for multiple interrupts has been designed to work with the opb_intc
peripheral that is a part of the standard EDK distribution. Other interrupt controllers will
need the relevant support routines in the mb-hw.c, ppc-hw.c and the intr.c,h files, modified
accordingly. Xilkernel also recognizes only interrupts connected through only one level of
Interrupt Handling
interrupt controllers. Cascaded interrupt controllers are not supported. The Xilkernel user-
level interrupt handling API, is described below.
Chapter 5: Xilkernel
Kernel Customization
Xilkernel is highly customizable. As described in previous sections, modules and
individual parameters can be changed to suit the user application. The XPS GUI system
provides excellent support for easy configuration of parameters of Xilkernel, using the
software platform settings dialog. Refer to Chapter 2, “Xilinx Platform Studio (XPS)” in the
Embedded Systems Tools Guide for more details. In order to customize a module in the kernel,
a parameter with the name of the category set to true must be defined in the MSS. For
example, to customize the pthread module,
parameter config_pthread_support = true
is required in the OS specification. Not defining a configurable module’s config_
parameter will mean that the module will be configured out.
An MSS snippet for configuring OS Xilkernel for a PPC system is given below:
PARAMETER os_name = xilkernel
PARAMETER os_ver = 2.00.a
PARAMETER stdin = RS232
PARAMETER stdout = RS232
PARAMETER proc_instance = ppc405_0
PARAMETER linker_script_specification = true
PARAMETER vec_mem_start = 0xffff0000
PARAMETER vec_mem_size = 16k
PARAMETER data_mem_start = 0xffff4000
PARAMETER data_mem_size = 20k
PARAMETER code_mem_start = 0xffff9000
PARAMETER code_mem_size = 28k
PARAMETER config_process = true
PARAMETER sched_type = 2
PARAMETER config_shm = true
PARAMETER shm_table = (100)
Kernel Customization
Chapter 5: Xilkernel
part of an application that is in the kernel bundle mode. If there are no kernel bundle
applications, then it should be in one of the compiled kernel sources.
Table 5-2: User initialization routine parameters
Kernel Customization
Customizing Scheduling
The user can configure the type of scheduler used and the number of priorities used for the
Scheduler module. The configurable parameters are given below.
Chapter 5: Xilkernel
Customizing Semaphore
The user can optionally select to include semaphores, maximum number of semaphores
and semaphore queue length. The following are the parameters used for configuration.
Kernel Customization
Chapter 5: Xilkernel
Kernel Customization
Chapter 5: Xilkernel
Debugging Xilkernel
In kernel bundled executable mode, there is a single file that can serve as the target for
debugging. Therefore all kernel bundled user applications can be debugged together using
GDB. However this is not the case for separate executable mode. Therefore, separate
executable applications can currently, not be debugged with XMD and GDB.
Memory Footprint
The size of Xilkernel depends on the user configuration. It is small in size and can fit in
different configurations. The following is the memory size output from GNU size utility
for the kernel. The image for the PPC version of Xilkernel includes the code for the
exception and interrupt vectors, which is by design entitled to occupy 8 Kb of text space.
Therefore the text sizes reported below include this 8 Kb of vector code space. Xilkernel has
been tested with the GCC optimization flag of -O2, These numbers below are also from the
same optimization level.
System Initialization
The entry point for the kernel is the main() routine defined in main.c. The first action
performed is hardware specific initialization. This includes registering the interrupt
handlers and configuring the system timer. This portion of the initialization depends upon
the kind of hardware that is present in the system. Interrupts/exceptions are not enabled
after completing hw_init(). If the user has required user_init() to be invoked as a part of the
system initialization, then user_init() is invoked next (This applies only if the user_init
routine is within the symbolic scope of the rest of the kernel). The sys_init() routine is
entered next. This routine performs initialization of each module such as processes,
threads, etc. Specifically, it initializes the following things, in order.
1. Internal process context structures
2. Ready queues
3. Pthread module
4. Semaphore module
5. Message Queue module
6. Shared memory module
7. Memory allocation module
8. Idle task creation
9. Static separate executable process creation
10. Static kernel bundled process creation
Chapter 5: Xilkernel
Limitations
Xilkernel currently has the following limitations.
x The PPC xilkernel image size is contributed significantly (8 Kb) to by the exception
vector code. In general, Xilkernel can be further optimized for size.
x Timer support is not complete in both versions of Xilkernel.
x POSIX error reporting structure is not fully complete. Therefore, the errno feature is
not supported in the POSIX calls.
x There is restriction on rescheduling tasks within an interrupt handler (described in
earlier sections). This means that usage of semaphores, mutex locks, message queues
and creating or manipulating processes and threads cannot occur within interrupt
handlers.
Future Enhancements
Apart from overcoming the above limitations, future enhancements will focus on
supporting the following features.
x Memory protection (with some hardware support).
x Better memory allocation and memory mapping functionality.
x Preventing priority inversion with priority inheritance.
x Supporting debugging of separate executable applications with GDB.
x Alarms and Timers.
x Migrating to POSIX scheduling schemes (SCHED_FIFO and SCHED_RR schemes in a
common priority based implementation).
x POSIX signals.
Modifying Xilkernel
Users can further customize Xilkernel by changing the actual code base. To work with a
custom copy of Xilkernel, users first copy the Xilkernel source folder (xilkernel_v2_00_a)
from within the EDK installation and place it under the bsp folder of the project folder. For
example, <..../myproject/bsp/xilkernel_v2_00_a>. Libgen now picks up this source folder of
Xilkernel for compilation, since it looks for Xilkernel sources first under the bsp folder
before picking it up from the standard installation. Refer to “Xilkernel File Organization”
for more information on the organization of the Xilkernel sources. Xilkernel sources have
been written in an elementary and intuitive style and include comment blocks above each
significant function. Each source file also carries a comment block indicating its role.
User Guide
Refer to the “Using Xilkernel” chapter in the Platform Studio User Guide for detailed steps
on configuring and using Xilkernel. Information on how to develop, build, and download
User Guide
applications is also present in that chapter. Some example systems and applications are
illustrated. These design examples illustrate all the features of Xilkernel and therefore will
be very useful for users who would like to quickly get started with Xilkernel.
Chapter 5: Xilkernel
Chapter 6
LibXil Net
This chapter describes the network library for Embedded processors, libXilNet. The library
includes functions to support the TCP/IP stack and the higher level application
programming interface (Socket APIs).
The chapter contains the following sections.
x “Overview”
x “LibXilNet Functions”
x “Protocols Supported”
x “Library Architecture”
x “Protocol Function Description”
x “Current Restrictions”
x “Functions of LibXilNet”
x “LibGen Customization”
x “Using XilNet in Application”
Overview
The Embedded Development Kit (EDK) networking library, libXilNet, allows a processor
to connect to the internet. LibXilNet includes functions for handling the TCP/IP stack
protocols. It also provides a simple set of Sockets Application Programming Interface
(APIs) functions enabling network programming. Lib Xil Net supports multiple
connections (through Sockets interface) and hence enables multiple client support. This
chapter describes the various functions of LibXilNet.
LibXilNet Functions
Quick Glance
Table 6-1 presents a list of functions provided by the LibXilNet at a glance.
Protocols Supported
Protocols Supported
LibXilNet supports drivers and functions for the Sockets API and protocols of TCP/IP
stack. The following list enumerates them.
x Ethernet Encapsulation (RFC 894)
x Address Resolution Protocol (ARP - RFC 826)
x Internet Protocol (IP - RFC 791)
x Internet Control Management Protocol (ICMP - RFC 792)
x Transmission Control Protocol (TCP - RFC 793)
x User Datagram Protocol (UDP - RFC 768)
x Sockets API
Library Architecture
Figure 6-1 gives the architecture of libXilNet. Higher Level applications like HTTP server,
TFTP (Trivial File Transfer Protocol), PING etc., uses API functions to use the libXilNet
library
Demultiplexing
based on
connections
ICMP TCP UDP
Demultiplexing based
on protocal value in
IP Header
ARP IP
Demultiplexing based on
frame type in Ethernet Header
Ethernet
Driver
Incoming Frame
MAC
Driver
LibXilNet Architecture
UG111_07_111903
Ethernet Drivers
Ethernet drivers perform the encapsulation/removal of ethernet headers on the payload in
accordance with the RFC 894. Based on the type of payload (IP or ARP), the drivers call the
corresponding protocol callback function. A Hardware Address Table is maintained for
mapping 48-bits ethernet address to 32-bits IP address.
IP (RFC 791)
IPv4 datagrams are used by the higher level protocols like ICMP, TCP, and UDP for
receiving/sending data. A callback function is provided for ethernet drivers which is
invoked whenever there is an IP datagram as a payload in an ethernet frame. Minimal
processing of the source IP address check is performed before the corresponding higher
level protocol (ICMP, TCP, UDP) is called. Checksum is calculated on all the outgoing IP
datagrams before calling the ethernet callback function for sending the data. An IP address
for a Embedded Processor needs to be programmed before using it for communication. An
IP address initializing function is provided. Refer to the table describing the various
routines for further details on the function. Currently no IP fragmentation is performed on
the outgoing datagrams. The Hardware address table is updated with the new IP/Ethernet
address pair if an IP packet was destined for the processor.
outgoing UDP datagram. The number of UDP connections that can be supported
simultaneously is configurable.
Sockets API
Functions for creating sockets (TCP/UDP), managing sockets, sending and receiving data
on UDP and TCP sockets are provided. High level network applications need to use these
functions for performing data communication. Refer to Table 6-1 for further details.
Buffer Management
XiNet stack is geared to work with smaller FPGA devices and hence minimal buffer
management is provided. The stack uses two global buffers - sendbuf, recvbuf - to send
and receive ethernet frames. User code can either allocate a buffer or use sendbuf to send
packets from the application. When sendbuf is used to transmit packets, user code is
responsible to place the application data at the right offset from start of sendbuf
accounting for all layers of stack starting from ethernet header.
Current Restrictions
Certain restrictions apply to the EDK libXilNet library software. These are
x Only server functionalities for ARP - This means ARP requests are not being
generated from the processor
x Only server functionalities in libXilNet - This means no client application
development support provided in libXilNet.
x No timers in TCP - Since there are no timers used, every "send" over a TCP connection
waits for an "ack" before performing the next "send".
Functions of LibXilNet
The following table gives the list of functions in libXilNet and their descriptions
Functions of LibXilNet
Parameters None
Returns 1 for success and 0 for failure
Description Initialize the xilinx internal sockets for use.
Includes xilsock.h
Functions of LibXilNet
Parameters addr: 48-bit colon separated hexa decimal ethernet address string
Returns None
Description Initialize the source ethernet address used in the libXil Net library
to addr. This function has to be called at the start of a user program
with a 48-bit, colon separated, hexa decimal ethernet address
string for source ethernet address before starting to use other
functions of libXil Net library. This address will be used as the
source ethernet address in all the ethernet frames.
Includes xilsock.h
mac.h
Functions of LibXilNet
Parameters None
Returns None
Description Initializes Hardware Address Table. This function must be called
in the user program before using other functions of LibXilNet.
Includes xilsock.h
mac.h
Functions of LibXilNet
Functions of LibXilNet
Parameters None
Returns None
Description Initialize all UDP connections so that the states of all the
connections specify that they are usable.
Includes xilsock.h
Parameters None
Returns None
Description Initialize all TCP connections so that the states of all the
connections specify that they are usable.
Includes xilsock.h
LibGen Customization
LibGen Customization
XilNet library is customized through LibGen tool. Here is a snippet from system.mss file
for specifying LibXilNet.
BEGIN LIBRARY
PARAMETER LIBRARY_NAME = xilnet
PARAMETER LIBRARY_VER = 1.00.a
PARAMETER device_type = ethernet
PARAMETER emac_type = emac
END
LibXilNet has the infrastructure to support different networking devices. The parameter
device_type can take - ethernet, serial, host as values. Currently however ethernet is the
device type that has been tested.
With ethernet device type, LibXilNet can be used with either the regular ethernet core or
the lite version, ethernetlite.
The parameter emac_type can take - emac, emaclite as values. This configures XilNet to be
used with either Emac of EmacLite driver.
Chapter 7
LibXil File
Xilinx libraries provide block access to file systems and devices using standard calls such
as open, close, read, and write. These routines form the LibXil File module of the libraries.
A system can be configured to use the LibXil File module, using the Library Generator
(libgen).
This chapter contains the following sections.
x “Overview”
x “Module Usage”
x “Module Routines”
x “Libgen Support”
x “Limitations”
Overview
The LibXil library provides block access to files and devices through the LibXil File
module. This module provides standard routines such as open, close, read, and write to
access file systems and devices.
The module LibXil File can also be easily modified to incorporate additional file systems
and devices. This module implements a subset of operating system level functions.
Module Usage
A file or a device is opened for read and write using the open call in the library. The library
maintains a list of open files and devices. Read and write commands can be issued to
access blocks of data from the open files and devices.
Module Routines
Functions
int open (const char *name, int flags, int mode)
int close (int fd)
int read (int fd, char* buf, int nbytes)
int write (int fd, char* buf, int nbytes)
Functions
long lseek (int fd, long offset, int whence)
int chdir (const char *buf)
const char* getcwd (void)
Module Routines
Parameters None
Returns The current working directory.
Description Get the absolute path for the current working directory.
Includes xilfile.h
xparameters.h
Libgen Support
For example, to access two uarts ( myuart1 and myuart2) and the memory file system (
xilmfs ) , use the following code snippet.
BEGIN LIBRARY
PARAMETER LIBRARY_NAME = xilfile
PARAMETER LIBRARY_VER = 1.00.a
PARAMETER peripherals = ( ("myuart", "/dev/myuart") , ("myuart2",
"/dev/myuart2") )
PARAMETER filesys = (( "xilmfs" , "/dev/mfs" ))
END
System Initialization
LibGen also generates the system initialization file, which is compiled into the LibXil
library. This file initialized the data structure required by the LibXil File module, such as
the Device tables and the File System table. This routine also initializes STDIN, STDOUT
and STDERR, if present.
Limitations
LibXil File module currently enforces the following restrictions:
1. Note that there is no instance name for filesystem and other Xilinx Microkernel modules. Hence, the name of
the filesystem should be used instead of the instance name.
Limitations
x Only one instance of a File System can be mounted. This file system and the mount
point has to be indicated in the Microprocessor Software Specification (MSS) file.
x Files cannot have names starting with /dev, since it is a reserved word to be used only
for accessing devices.
x Currently LibXil File has support only for 1 file system (LibXil Memory File System)
and 3 devices (UART, UARTlite and GPIO).
x Only devices can be assigned as STDIN, STDOUT and STDERR.
Chapter 8
Overview
The XilFatfs filesystem access library provides read/write access to files stored on a Xilinx
SystemACE CompactFlash or IBM microdrive device. This library requires the underlying
hardware platform to contain all of the following:
x OPB SYSACE Interface Controller - Logicore module
x SystemACE controller and CompactFlash connector
x 128MB or 256MB CompactFlash card formatted with a FAT16, FAT12 or FAT32 file
system or an IBM microdrive formatted with a FAT16, FAT12 or FAT32 file system
Caution! FAT16 is required for SystemACE to directly configure the FPGA but the XilFatfs
library can work with the SystemACE hardware to support FAT12 and FAT32 as well.
See the documentation on OPB SYSACE Interface Controller in the Processor IP Reference
Guide for more details on the hardware.
If this library is to be used in a MicroBlaze system, and speed is of concern, it is
recommended that the MicroBlaze processor be configured to include a hardware barrel
shifter. See the MicroBlaze documentation for more information on including the barrel
shifter.
Users can easily copy files to the flash device from their PC by plugging the flash or
microdrive into a suitable USB adapter or similar device.
XilFatfs Functions
This section presents a list of functions provided by the XilFatfs. Table 8-1 provides the
function names with signature at a glance.
Parameters file is the name of the file on the flash device. address is the
starting(base) address of the file system memory
mode is restricted to “r” in this version
Returns A non zero file handle on success
0 for failure
Description The file name should follow the Microsoft 8.3 naming standard
with a file name of up to 8 characters, followed by a ‘.’ and a 3
character extension. In this version of the library, the 3 character
extension is mandatory so a sample file might be called test.txt
This function returns a file handle that has to be used for
subsequent calls to read or close the file
If the named file does not exist on the device 0 is returned
Includes sysace_stdio.h
XilFatfs Functions
int sysace_fread (void *buffer, int size, int count, void *stream)
int sysace_fwrite (void *buffer, int size, int count, void *stream)
LibGen Customization
XilFatfs file system can be integrated with a system using the following snippet in the mss
file. There are
BEGIN LIBRARY
parameter LIBRARY_NAME = xilfatfs
parameter LIBRARY_VER = 1.10.a
# The following 3 parameters are optional and their default value is ‘n’
parameter CONFIG_WRITE = y
parameter CONFIG_DIR_SUPPORT = y
parameter CONFIG_FAT12 = y
END
The CONFIG_WRITE parameter when set to ‘y’, adds write capabilities to the library.
LibGen Customization
The CONFIG_DIR_SUPPORT parameter when set to ‘y’, adds the mkdir and chdir
functions to the library.
The CONFIG_FAT12 parameter when set to ‘y’ configures the library to work with FAT12
file systems. Otherwise the library works with both FAT16 and FAT32 file systems.
Chapter 9
Overview
The Memory File System (MFS) component, LibXil MFS, provides users the capability to
manage program memory in the form of file handles. Users can create directories, and can
have files within each directory. The file system can be accessed from the high level
C-language through function calls specific to the file system. Alternatively, users can also
manage files through the standard C language functions like open provided in XilFile.
MFS Functions
Quick Glance
This section presents a list of functions provided by the MFS. Table 9-1 provides the
function names with signature at a glance.
MFS Functions
Parameters numbytes is the number of bytes of memory available for the file
system
address is the starting(base) address of the file system memory
status is one of MFSINIT_NEW, MFSINIT_IMAGE or
MFSINIT_ROM_IMAGE
MFS Functions
Parameters fd: File descriptor return by open; passed to this function by caller
filename: Pointer to file name at the current position in the
directory in MFS; this value is filled in by this function
filesize: Pointer to a value filled in by this function: Size in bytes of
filename, if it is a regular file; Number of directory entries if
filename is a directory
filetype: Pointer to a value filled in by this function:
MFS_BLOCK_TYPE_FILE if filename is a regular file;
MFS_BLOCK_TYPE_DIR if filename is a directory
Returns On Success return number of bytes read.
On Failure return 1
Description Read the current directory entry and advance the internal pointer
to the next directory entry. filename, filetype and filesize are pointers
to values stored in the current directory entry
Includes xilmfs.h
MFS Functions
Utility Functions
The following few functions are utility functions that can be used along with Xilinx MFS.
These functions are defined in mfs_filesys_util.c and are not declared in xilmfs.h. They
must be declared by the user if needed.
int mfs_ls (void)
Parameters None
Returns On success return 1
On failure return 0
Description List contents of current directory on STDOUT.
Includes xilmfs.h
Additional Utilities
Additional Utilities
A program called mfsgen is provided along with the MFS library. mfsgen can be used to
create an MFS memory image on a host system that can subsequently be downloaded to
the embedded system memory. mfsgen itself links to libXilMFS and is compiled to run on
the host machine rather than the target MicroBlaze or PowerPC system. Conceptually, this
is similar to the familiar zip or tar programs. The source code for mfsgen is provided in the
file mfsgen.c in the utils sub-directory. The executable image should be in the path.
An entire directory hierarchy on the host system can be copied to a local MFS file image
using mfsgen. This file image can then be downloaded on to the memory of the embedded
system for creating a pre-loaded file system. A few test programs are included to show
how this is done. More information can be found in the readme.txt file in the utils sub-
directory and the “Using XilMFS” chapter in the Platform Studio User Guide.
Usage: mfsgen -txcvsbf [mfs_filename] [num_blocks] <filelist>
Specify exactly one of c,t,x modes
t: list the files in the mfs file system image
c: create an mfs file system image using the list of files specified on the command line
- Directories specified in this list are traversed recursively
x: extract the mfs file system from image to host file system
v: verbose mode
f: specify the host file name (mfs_filename) where the mfs file system image is stored
- If the f option is specified the mfs filename should be specified
- If the f option is omitted the default file name is filesystem.mfs
s: switch endianness
b: number of blocks - should be more than 2
- If the b option is specified the num_blocks value should be specifed
- If the b option is omitted the default value of num_blocks is 5000
- The b option is meaningful only when used in conjunction with the c option
C-like access
The user can choose not to deal with the details of the file system by using the standard C-
like interface provided by Xil File. It provides the basic C stdio functions like open, close,
read, write, and seek. These functions have identical signature as those in the standard
ANSI-C. Thus any program with file operations performed using these functions can be
easily ported to MFS by interfacing the MFS in conjunction with library Xilfile.
LibGen Customization
Memory file system can be integrated with a system using the following snippet in the mss
file. The memory file system should be instantiated with the name xilmfs. The attributes
used by libgen and their descriptions are given in Table 9-2.
BEGIN LIBRARY
parameter LIBRARY_NAME = xilmfs
parameter LIBRARY_VER = 1.00.a
Chapter 10
LibXil Profile
This chapter describes the profiling library for embedded processors, libXil Profile. The
chapter contains the following sections:
x “Overview”
x “Features”
x “Profiling Model”
x “Customizing xilprofile”
x “Building Applications”
x “Generating GPROF Files”
x “XilProfile Code Description”
x “Limitations”
Overview
Profiling a program running on hardware (board), provides insight into program
execution and identifies where it spends most time. Profiling on hardware is faster and the
interaction of program with memory and other peripherals can be more accurately
captured. LibXil Profile is a software intrusive profile library that generates Call Graph and
Histogram information of program running on board. Executing the program on hardware
generates the profiling information which is stored on the hardware. XMD generates
output file from the data, which can be read by GNU gprof tools (mb-gprof) to generate the
profiling information.Profiling is supported for the MicroBlaze processor.
Features
LibXil Profile library has the following features:
x Provides Histogram (flat profile) and Call Graph information.
i Histogram: Shows how much time the program spent in each function and how
many times the function was called.
i Call Graph: Shows for each function, which functions called it, which other
functions it called and how many times.
x Profiling parameters are configurable - Sampling Frequency, Histogram Bin Size and
Timer to use.
x Memory location and size to store profiling is flexible and configurable based on
program requirements.
Profiling Model
The libxil profile library, libxilprofile.a is generated and customized for software platform
by instantiating the xilprofile library. Running LibGen will create this library. For more
details of Profiling flow refer to the “Profiling Embedded Designs” chapter in the Platform
Studio User Guide.
When the profile option -pg is specified to the compiler (mb-gcc and powerpc-eabi-gcc),
this library is automatically linked with the application to profile. The generated
executable file contains code to generate profile information.
When the program is executed on board, the profile information is stored at the memory
location specified by the user. XMD is profile library “aware” and generates the gprof
compatible output file based on profile data.
Note: The xilprofile library does not have any explicit application API. The library is linked due to
profile calls (_mcount) introduced by gcc for profiling. The are some global variables that need to be
set in the application for using the library. This is explained in the later sections.
Customizing xilprofile
The xilprofile library can be customized for an application. Following is the list of
PARAMETERS for the library.
Building Applications
The memory needed for storing profile information is allocated in the user application. The
memory can be either an array allocated in program or any memory in the hardware
system. The latter gives the flexibility to specify any available memory in the system
without changing the program’s size or custom linker script. This memory is specified to
xilprofile library by two pointer variables in the application.
x char *memstart - Points to start of memory location.
x char *memend - Points to end of memory location.
MicroBlaze Configuration :
--------------------------
Version............................2.00.a
No of PC Breakpoints...............4
No of Read Addr/Data Watchpoints...1
No of Write Addr/Data Watchpoints..1
Instruction Cache Support..........off
Data Cache Support.................off
****************************************************************
** Profiling Memory Test
** Executable: microblaze_0/code/executable.elf
** Memory Allocated: 4200
Limitations
x _gmonparam - Data stored during profiling and information about the data. Refer
profile.h file for more details on this structure.
Limitations
The profiled program (text section) should exist as contiguous memory.
Chapter 11
lwIP Library
Overview
This chapter describes the Embedded Development Kit (EDK) port of the third party
network library, Light Weight IP (lwIP), for embedded processors. The chapter details the
port of the lwIP library for PowerPC and MicroBlaze processors. It contains the following
sections:
x “Overview”
x “PowerPC System”
x “MicroBlaze System”
x “Setting Up lwIP in EDK”
x “Designing an lwIP Application”
x “Example lwIP Application”
lwIP is an open source implementation of the TCP/IP protocol suite. The lwIP library
supports two interfaces - raw API, BSD style Sockets API. EDK has been ported to work
with the raw API interface of the library. The features of the lwIP library are :
x IP (Internet Protocol) including packet forwarding on multiple interfaces
x ICMP (Internet Control Message Protocl)
x UDP (User Datagram Protocol)
x TCP (Transmission Control Protocol)
x .Raw API interface support for applications
The raw API provided by lwIP is the lowest level interface of the stack. It has two modes of
operation : Event and Callback. The EDK port uses the Callback mode. lwIP stack
maintains internal timers for TCP round trip calculations, retransmissions and other TCP
facilities. For this purpose, the lwIP timer functions must be called periodically. This is
achieved by using the 64-bit hardware timer in PowerPC. For MicroBlaze an external timer
is required. The system design involved for both MicroBlaze and PowerPC are discussed
in the following sections.
PowerPC System
Figure 11-1 shows an example hardware design of a PowerPC based system for lwIP. The
system requires a 10/100 ethernet core for performing the network transactions. The built-
in hardware timer is used to call the lwIP timer functions periodically.
PLB OPB
SDRAM 10/100
DSPLB MEMC Ethernet
ISPLB
INT
BRAM 32 KB UART
MEMC BRAM 16450
PPC405
Non-Crit PLB2OPB
INTC BRIDGE
GPIO
UG114_11_01_051404
MicroBlaze System
MicroBlaze does not supoprt an in-built timer. An OPB based timer provides the timer
functionality. The system uses the OPB based 10/100 regular ethernet core. A diagram of
an example MicroBlaze system design is shown in Figure 11-2.
OPB
SDRAM
MEMC
MICROBLAZE ILMB DLMB
10/100
ILMB Ethernet
DLMB
IOPB MDM
DOPB
Interrupt GPIO
UART
BRAM 32K BRAM 16550
MEMC BRAM MEMC
OPB
TIMER
UG114_11_02_051404
Memory Management
Memory Management
There are two types of memory management in lwIP; the heap memory (mem) and the
static memory pools (memp). The pbuf management is a hybrid since it both manages its
own memory (th pbuf pool) and uses the heap (mem).
The mem is a heap memory manager, such as the C malloc/free manager. A block of
memory is requsted with a call to mem_malloc( ) and the memory is freed with a call to
mem_free( ). This is used by code that allocates memory of diffrent sizes. An example is
when contents of a packet needs to be copied into a buffer - since the size of the packet isn’t
known beforehand, the memory is allocated from the heap.
The memp, on the other hand, uses a set of pools of fixed size memory blocks. This is used
by the lwIP stack code to allocate predefined memory blocks. An example is for lwIP stack
to allocate memory for TCP protocol control blocks.
The pbufs are used to hold packet data. These are to be used by a network device driver
who needs to allocate buffers quickly. The memory options are defined in lwipopts.h file.
The memory options in lwipopts.h are as follows:
END
libgen Customization
lwIP library is customized through libgen tool. Here is a snippet from system.mss file for
specifying lwIP library.
BEGIN LIBRARY
PARAMETER LIBRARY_NAME = lwip
PARAMETER LIBRARY_VER = 1.00.a
PARAMETER EMAC_INSTANCES =
((my_opb_ethernet,0x00,0x0A,0x35,0x00,0x22,0x20))
END
lwIP has the infrastructure to support multiple ethernet interfaces. The parameter
emac_instances is an array. It takes in the instance name of an ethernet core (specified in
the MHS file) and the 48-bit MAC address corresponding to it. This configures lwIP to use
a particular ethernet instance with the 48-bit MAC address.
Initializing lwIP
lwIP requires the application to call several initialization routines. The following is a code
snippet that illustrates the initialization routines required for lwIP.
/***************************************************************
pbuf_init();
netif_init();
tcp_init();
/***************************************************************
Table 11-3: TCP Events, Callbacks, and Hot to Register Callback Events
Event Callback Register with lwIP
TCP connection established *accept() tcp_accept()
TCP Data Acknowledged *sent() tcp_sent()
by Remote Host
TCP Data Received *recv() tcp_recv()
The following section, “Raw APO Functions for TCP,” lists a subset of TCP related
functions. For a complete list of functions for other protocols, see:
($XILINX_EDK/sw/lib/sw_services/lwip_v1_00_a/src/lwip/doc/rawapi.txt)
void* tcp_init ()
This function must be called first to initialize the lwIP stack
void tcp_tmr()
This function must be called every TCP_TMR_INTERVAL milliseconds (defined in file
lwipopts.h). There are two lower level timer functions which are called inside tcp_tmr( ). The
example application calls these functions directly - they are: tcp_slowtmr( ) and
tcp_fasttmr( ).
C Program
The application is split among the following C and headerf files.
FileName : echo_main.c
/*
/*
permission.
*
. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ‘‘AS IS’’ AND ANY EXPRESS OR
/* Xilinx Includes */
#include "xuartns550_l.h"
#include "xtime_l.h"
#include "xparameters.h"
#include "xcache_l.h"
#include "xgpio_l.h"
/* lwIP Includes */
#include "netif/xemacif.h"
#include "lwip/tcp.h"
#include "lwip/memp.h"
#include "netif/etharp.h"
#include "echo.h"
* TCP_TMR_INTERVAL )
// Upper 6 bytes of MAC - Xilinx Ethernet OUI = 00-0A-35
#define XILINX_MAC_OUI0 0x00
#define XILINX_MAC_OUI1 0x00
#define XILINX_MAC_OUI2 0x00
/* defined in lwip/src/core/tcp.c */
extern u32_t tcp_ticks;
/*------------------------------------------------------------------*/
int bb;
char temp;
for(bb=0;bb<4;bb++)
{
temp = address_array[bb];
if(bb!=0) xil_printf(".");
xil_printf("%d", (int) temp);
}
}
/*------------------------------------------------------------------*/
/* show dashed hex prints a dashed hex address to the UART */
/*------------------------------------------------------------------*/
static void show_dashed_hex( int bytes, char *address_array)
{
for(bb=0;bb<bytes;bb++)
{
if(bb !=0) xil_printf("-");
xil_printf("%02X", (int) address_array[bb]);
}
}
/*------------------------------------------------------------------*/
/* my_tmr - Called Periodically to dispatch TCP and ARP timers */
/*------------------------------------------------------------------*/
void my_tmr(void)
{
++my_timer;
if(my_timer == 10) {
my_timer = 0;
}
if(my_timer & 1) {
tcp_fasttmr();
}
if(my_timer == 0 || my_timer == 5) {
/*------------------------------------------------------------------*/
/* print_app_header - prints the legal header */
/*------------------------------------------------------------------*/
void print_app_header()
{
xil_printf("\n\n\n\n\n\n\n\n\n");
xil_printf("##########################################################
##########
\n");
xil_printf("##########################################################
##########
\n");
}
/*------------------------------------------------------------------*/
/* main function */
/*------------------------------------------------------------------*/
int main_main ()
XILINX_MAC_OUI2,
/*----------------------------------------------------------------
/* Disable Interrupts */
XIo_Out8(UART_BASEADDR + XUN_LCR_OFFSET, 0UL);
XIo_Out8(UART_BASEADDR + XUN_IER_OFFSET, 0UL);
/* Clear Latches */
XIo_In8(UART_BASEADDR + XUN_LSR_OFFSET);
XIo_In8(UART_BASEADDR + XUN_IIR_OFFSET);
XIo_In8(UART_BASEADDR + XUN_MSR_OFFSET);
xil_printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n");
xil_printf("Starting Up...
\n");
xil_printf("Console: 16550 initialized.
\n");
/*---------------------------------------------------------------*/
/* Timer Inits */
/*---------------------------------------------------------------*/
ml_offset = LWIP_TIMER_CYCLES;
/*---------------------------------------------------------------*/
stats_init();
#endif /* STATS */
xil_printf("Initializing Memory Structures.");
sys_init();
mem_init();
xil_printf(".");
memp_init();
xil_printf(".");
pbuf_init();
xil_printf(" done.
\n");
/*---------------------------------------------------------------*/
/* Initial Header and Menus. Do this before the netif_init() so */
/* we can change the MAC Address and IP addresses if needed */
/*---------------------------------------------------------------*/
while(init_wait--);
print_app_header();
fullmac[0] = XILINX_MAC_OUI0;
fullmac[1] = XILINX_MAC_OUI1;
fullmac[2] = XILINX_MAC_OUI2;
fullmac[3] = low_mac[0];
fullmac[4] = low_mac[1];
fullmac[5] = low_mac[2];
/*---------------------------------------------------------------*/
gateway
IP4_ADDR(&ipaddr, ip[0],ip[1],ip[2],ip[3]); //Set ip
IP4_ADDR(&netmask,subnet[0],subnet[1],subnet[2],subnet[3]); //Set
subnet msk
/*---------------------------------------------------------------*/
xil_printf("
\n");
/*---------------------------------------------------------------*/
/* Initialize netif */
/*---------------------------------------------------------------*/
netif_init();
/*---------------------------------------------------------------*/
/*---------------------------------------------------------------*/
&netmask,
&gw,
&XEmacIf_ConfigTable[0],
xemacif_init,
ip_input
);
netif_set_default(default_netif);
/*---------------------------------------------------------------*/
/* create new tcp pcb and start applications */
/*---------------------------------------------------------------*/
\n");
echo_init();
while (1) {
while (waiting_for_timer) {
xemacif_input(default_netif);
XTime_GetTime(&ml_new);
if ( ml_new >= ml_base ) {
waiting_for_timer = 0;
ml_base = ml_new + ml_offset;
}
}
// Call my_tmr() every ml_offset cycles
my_tmr();
waiting_for_timer = 1;
}
return (1);
}
int main ()
{
/*---------------------------------------------------------------*/
/* Enable instruction and data cache -this must be done first because
*/
/* the Memec Design Virtex-II Dev Boards (rev1 and rev2) have the
SDRAM */
/* byte enables tied together on the board. Enabling the caches */
/* guarantees that all memory accesses are 32-bit aligned. */
/*---------------------------------------------------------------*/
XCache_EnableICache(0x80000001);
XCache_EnableDCache(0x80000001);
return main_main();
FileName : echo.c
/*
permission.
*
. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ‘‘AS IS’’ AND ANY EXPRESS OR
IMPLIED
. * OF SUCH DAMAGE. *
*
*/
#include "lwip/debug.h"
#include "lwip/stats.h"
#include "lwip/tcp.h"
#include "xparameters.h"
#include "echo.h"
struct echo_state {
struct pbuf *p;
u8_t failed;
#define FAILED_MAX 8
};
/*------------------------------------------------------------------*/
static void
echo_err(void *arg, err_t err)
{
xil_printf("echo_err
\n");
if(arg != NULL) {
pbuf_free(es->p);
mem_free(arg);
}
}
/*------------------------------------------------------------------*/
static void
close_conn(struct tcp_pcb *pcb, struct echo_state *es)
{
tcp_arg(pcb, NULL);
tcp_sent(pcb, NULL);
tcp_recv(pcb, NULL);
if(es != NULL) {
pbuf_free(es->p);
mem_free(es);
}
tcp_close(pcb);
xil_printf("Connection Closed
\n");
}
/*------------------------------------------------------------------*/
static void
send_buf(struct tcp_pcb *pcb, struct echo_state *es)
{
do {
q = es->p;
es->p = pbuf_dechain(q);
if(tcp_write(pcb, q->payload, q->len, 1) == ERR_MEM) {
pbuf_chain(q, es->p);
es->p = q;
return;
}
tcp_recved(pcb, q->len);
pbuf_free(q);
} while(es->p != NULL);
}
/*------------------------------------------------------------------*/
static err_t
echo_poll(void *arg, struct tcp_pcb *pcb)
{
if(arg == NULL) {
return tcp_close(pcb);
}
es = arg;
if(es->p != NULL) {
++es->failed;
send_buf(pcb, es);
return ERR_OK;
}
/*------------------------------------------------------------------*/
static err_t
echo_sent(void *arg, struct tcp_pcb *pcb, u16_t len)
{
es = arg;
send_buf(pcb, es);
}
return ERR_OK;
}
/*------------------------------------------------------------------*/
static err_t
echo_recv(void *arg, struct tcp_pcb *pcb, struct pbuf *p, err_t err)
{
es = arg;
if(p == NULL) {
close_conn(pcb, es);
return ERR_OK;
if(es->p != NULL) {
pbuf_chain(es->p, p);
} else {
es->p = p;
send_buf(pcb, es);
return ERR_OK;
}
/*------------------------------------------------------------------*/
static err_t
echo_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
tcp_setprio(pcb, TCP_PRIO_MIN);
/* Allocate memory for the structure that holds the state of the
connection. */
es = mem_malloc(sizeof(struct echo_state));
if(es == NULL) {
xil_printf("could not malloc memory for echo_state
\n");
return ERR_MEM;
}
/* Tell TCP that this is the structure we wish to be passed for our
callbacks. */
tcp_arg(pcb, es);
xil_printf("Connection Established
\n");
return ERR_OK;
}
/*------------------------------------------------------------------*/
void
echo_init(void)
{
pcb = tcp_new();
tcp_bind(pcb, IP_ADDR_ANY, ECHO_PORT);
pcb = tcp_listen(pcb);
tcp_accept(pcb, echo_accept);
}
/*------------------------------------------------------------------*/
FileName : echo.h
#ifndef LWIP_ECHO_H
#define LWIP_ECHO_H
#define ECHO_PORT 7
void echo_init(void);
#endif
Linker script
The linker script used with the above example.
/*********************************************************************
*
. * AND YOU ARE RESPONSIBLE FOR OBTAINING ANY RIGHTS YOU MAY REQUIRE
*********************************************************************/
_STACK_SIZE = 1024k;
_HEAP_SIZE = 1024k;
MEMORY
{
sdram : ORIGIN = 0x00000000, LENGTH = 32M
bram : ORIGIN = 0xFFFF8000, LENGTH = 32K - 4
boot : ORIGIN = 0xfffffffc, LENGTH = 4
STARTUP(boot.o)
ENTRY(_boot)
GROUP(libxil.a libc.a)
SECTIONS
{
.vectors :
{
*(.vectors)
} > sdram
.data :
{
*(.data)
*(.got2)
*(.rodata)
*(.fixup)
} > sdram
.sbss :
{
. = ALIGN(4);
*(.sbss)
. = ALIGN(4);
} > sdram
__sbss_start = ADDR(.sbss);
__sbss_end = ADDR(.sbss) + SIZEOF(.sbss);
.bss :
{
. = ALIGN(4);
*(.bss)
*(COMMON)
. = ALIGN(4);
__bss_end = .;
} > sdram
__bss_start = ADDR(.bss);
.boot0 :
{
*(.boot0)
_end = .;
} > sdram
C Program
The application is split among the following C and headerf files.
FileName : echo_main.c
/*
/*
permission.
*
. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ‘‘AS IS’’ AND ANY EXPRESS OR
/* Xilinx Includes */
#include "xuartns550_l.h"
#include "xparameters.h"
#include "xgpio_l.h"
#include "xtmrctr_l.h"
/* lwIP Includes */
#include "netif/xemacif.h"
#include "lwip/tcp.h"
#include "lwip/memp.h"
#include "netif/etharp.h"
#include "echo.h"
#define UART_BASEADDR
XPAR_MYUART_16550_BASEADDR
#define UART_CLOCK
(XPAR_XUARTNS550_CLOCK_HZ)
#define UART_BAUDRATE
(115200)
* TCP_TMR_INTERVAL )
// Upper 6 bytes of MAC - Xilinx Ethernet OUI = 00-0A-35
#define XILINX_MAC_OUI0 0x00
#define XILINX_MAC_OUI1 0x00
#define XILINX_MAC_OUI2 0x00
/* defined in lwip/src/core/tcp.c */
extern u32_t tcp_ticks;
/*------------------------------------------------------------------*/
// show dotted decimal prints a dotted decimal address to the UART
/*------------------------------------------------------------------*/
static void show_dotted_decimal( char *address_array)
{
int bb;
unsigned char temp;
for(bb=0;bb<4;bb++)
{
temp = address_array[bb];
if(bb!=0) xil_printf(".");
xil_printf("%d", temp);
}
}
/*------------------------------------------------------------------*/
/* show dashed hex prints a dashed hex address to the UART */
/*------------------------------------------------------------------*/
static void show_dashed_hex( int bytes, char *address_array)
{
for(bb=0;bb<bytes;bb++)
{
if(bb !=0) xil_printf("-");
xil_printf("%02X", (int) address_array[bb]);
}
}
/*------------------------------------------------------------------*/
/* my_tmr - Called Periodically to dispatch TCP and ARP timers */
/*------------------------------------------------------------------*/
void my_tmr(void)
{
++my_timer;
if(my_timer == 10) {
my_timer = 0;
}
if(my_timer & 1) {
if(my_timer == 0 || my_timer == 5) {
}
}
/*------------------------------------------------------------------*/
/* print_app_header - prints the legal header */
/*------------------------------------------------------------------*/
void print_app_header()
{
xil_printf("\n\n\n\n\n\n\n\n
\n");
xil_printf("##########################################################
##########
\n");
xil_printf("# #
\n");
xil_printf("# XILINX IS PROVIDING THIS DESIGN, CODE, OR INFORMATION
’AS IS’ #
\n");
xil_printf("# SOLELY FOR USE IN DEVELOPING PROGRAMS AND SOLUTIONS FOR
#
\n");
xil_printf("# XILINX DEVICES.
#
\n");
xil_printf("# #
\n");
xil_printf("# (c) Copyright 2003, 2003 Xilinx, Inc.
#
\n");
xil_printf("# All rights reserved.
#
\n");
xil_printf("# #
\n");
xil_printf("##########################################################
##########
\n");
/*------------------------------------------------------------------*/
/* main function */
/*------------------------------------------------------------------*/
int main_main ()
{
/*------------------------------
microblaze_enable_interrupts();
/*----------------------------------------------------------------
/* 100 Mhz clock => 100 us for 1 clk tick. For 100ms, 1000 clk ticks
need to elapse */
XTmrCtr_mSetLoadReg(XPAR_OPB_TIMER_1_BASEADDR, 0, 10000);
XTmrCtr_mSetControlStatusReg(XPAR_OPB_TIMER_1_BASEADDR, 0,
XTC_CSR_INT_OCCURED_MASK | XTC_CSR_LOAD_MASK );
XTmrCtr_mSetControlStatusReg(XPAR_OPB_TIMER_1_BASEADDR, 0,
XTC_CSR_ENABLE_TMR_MASK | XTC_CSR_ENABLE_INT_MASK |
XTC_CSR_AUTO_RELOAD_MASK | XTC_CSR_DOWN_COUNT_MASK);
/*----------------------------------------------------------------
* Uart Init*----------------------------------------------------------
---------*/
/* Disable Interrupts */
/* Clear Latches */
XIo_In8(UART_BASEADDR + XUN_LSR_OFFSET);
XIo_In8(UART_BASEADDR + XUN_IIR_OFFSET);
XIo_In8(UART_BASEADDR + XUN_MSR_OFFSET);
xil_printf("\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
\n");
xil_printf("Starting Up...
\n");
/*------------------------------------------------------------------*/
/* Do LWIP System Inits */
/*---------------------------------------------------------------*/
#ifdef STATS
stats_init();
#endif /* STATS */
xil_printf("Initializing Memory Structures.");
sys_init();
mem_init();
xil_printf(".");
memp_init();
xil_printf(".");
pbuf_init();
xil_printf(" done.
\n");
/*---------------------------------------------------------------*/
/* Initial Header and Menus. Do this before the netif_init() so we
can */
/* change the MAC Address and IP addresses if needed */
/*---------------------------------------------------------------*/
while(init_wait--);
print_app_header();
fullmac[0] = XILINX_MAC_OUI0;
fullmac[1] = XILINX_MAC_OUI1;
fullmac[2] = XILINX_MAC_OUI2;
fullmac[3] = low_mac[0];
fullmac[4] = low_mac[1];
fullmac[5] = low_mac[2];
/*---------------------------------------------------------------*/
gateway
IP4_ADDR(&ipaddr, ip[0],ip[1],ip[2],ip[3]); //Set ip
IP4_ADDR(&netmask,subnet[0],subnet[1],subnet[2],subnet[3]); //Set
subnet msk
/*---------------------------------------------------------------*/
/*---------------------------------------------------------------*/
/* Initialize netif */
/*---------------------------------------------------------------*/
netif_init();
/*---------------------------------------------------------------*/
/*---------------------------------------------------------------*/
&netmask,
&gw,
&XEmacIf_ConfigTable[0],
xemacif_init,
ip_input
);
netif_set_default(default_netif);
/*---------------------------------------------------------------*/
/* create new tcp pcb and start applications */
/*---------------------------------------------------------------*/
\n");
echo_init();
app_running = 1;
while (1) {
while (waiting_for_timer) {
xemacif_input(default_netif);
}
my_tmr();
waiting_for_timer = 1;
}
return (1);
}
int main ()
{
/*---------------------------------------------------------------*/
/* Enable instruction and data cache-this must be done first because
*/
/* the Memec Design Virtex-II Dev Boards (rev1 and rev2) have the
SDRAM */
/* byte enables tied together on the board. Enabling the caches
*/
/* guarantees that all memory accesses are 32-bit aligned. */
/*---------------------------------------------------------------*/
return main_main();
}