This post explains how to build an application using RTEMS with lwIP TCP/IP stack. At present lwIP is supported with BBB.

For building the application you need 4 things

1. Build the RTEMS BBB BSP
2. lwIP stack compiled as a static library archive to be linked with the
3. Driver for ethernet controller compatible/ported to lwIP stack compiled as a static library archive to be linked with the application.
4. The application that can use these libraries.

1. Build RTEMS BBB BSP

     We need to build the RTEMS BBB BSP first so that our application can link to it. For use with      lwIP, we need to disable the cache. Networking is working only with cache disabled (Still debugging).

1. Clone the RTEMS master
     git clone https://github.com/RTEMS/rtems.git

2. Disable the cache . Apply this patch to the BSP
     https://raw.githubusercontent.com/ragunath3252/cpsw-lwip/master/BBB-cache-disable.patch

3.  Build rtems-master for beagleboneblack bsp. It will create the necessary libraries we need.
Pls refer to older posts on how to build rtems-master for BBB. We need to give an extra option during configure to tell where to install the built files. So the sequence of steps would be

a. BBB_CACHE_DISABLE=1 ${HOME}/git-rtems/configure  --prefix=${HOME}/sandbox/install --       target=arm-rtems4.11 --enable-rtemsbsp=beagleboneblack
    Prefix can be any folder where you want to install the files. I am giving
    "/home/ragu/development/install"
b. make
c. make install

The prefix option is important because in the future commands we will use this path to specify where the libraries are stored   

2. Building the lwIP stack
The lwIP stack is integrated with RTEMS source builder(RSB). You can clone the RSB and repo & build the lib. The following are the steps

a. Clone the RTEMS source builder repo
     git clone https://github.com/RTEMS/rtems-source-builder.git

b. cd rtems

c. ../source-builder/sb-set-builder --log=logfile --with-tools=compiler-path
    --host=x86_64-linux-gnu 4.11/net/lwip --prefix=bsp-install-path --rtems-bsp=arm/beagleboneblack  --target=arm-rtems4.11

here
--with-tools ---> assign it to RTEMS compiler path
--prefix        ---> Path where corresponding BSP is installed
--host ----> your host info

This will build and install the lib & header files in the path $prefix/$bsp/lwip

For  Example, for the command

../source-builder/sb-set-builder --log=logile --with-tools=/home/ragu/build_tools/rtems/compiler/4.11 --host=x86_64-linux-gnu 4.11/rtems-beagle-lwip --prefix=/home/ragu/build_tools/rtems_latest --rtems-bsp=arm/beagleboneblack --target=arm-rtems4.11

@ragu-ubuntu:~/work/gsoc/lwip/patch/test/rsb-make/rtems-source-builder/rtems$ ls -l /home/ragu/build_tools/rtems_latest/arm-rtems4.11/beagleboneblack/lwip/lib/
total 1796
-rw-r--r-- 1 root root 1641832 Aug 14 18:39 liblwip.a


3. Build driver library

The driver files are not integrated with RTEMS

a. Download the patch from the following link
https://raw.githubusercontent.com/ragunath3252/rtems-rsb-lwip/master/0001-CPSW-lwIP-driver-library-build-files.patch

b. Apply the patch to RTEMS RSB

c.  Execute the following command
../source-builder/sb-set-builder --log=modem --with-tools=/home/ragu/build_tools/rtems/compiler/4.11 --host=x86_64-linux-gnu 4.11/net/cpsw --prefix=/home/ragu/build_tools/rtems_latest --rtems-bsp=arm/beagleboneblack --target=arm-rtems4.11

Change your command as explained for lwip.This will install the driver library & include files in the $prefix/bsp/lwip

For example

ragu@ragu-ubuntu:~/work/gsoc/lwip/lwip-patch/rtems-source-builder$ ls -l /home/ragu/build_tools/rtems_latest/arm-rtems4.11/beagleboneblack/lwip/
total 8
drwxr-xr-x 6 root root 4096 Aug 14 18:41 include
drwxr-xr-x 2 root root 4096 Aug 14 18:41 lib
ragu@ragu-ubuntu:~/work/gsoc/lwip/lwip-patch/rtems-source-builder$ ls -l /home/ragu/build_tools/rtems_latest/arm-rtems4.11/beagleboneblack/lwip/include/
total 72
drwxr-xr-x 2 root root 4096 Aug 14 18:39 arch
-rwxr-xr-x 1 root root 5278 Aug 14 22:31 beaglebone.h
-rwxr-xr-x 1 root root 3170 Aug 14 22:31 cache.h
drwxr-xr-x 2 root root 4096 Aug 14 18:39 lwip
-rw-r--r-- 1 root root 1066 Aug 14 22:31 lwip_bbb.h
-rwxr-xr-x 1 root root 9090 Aug 14 22:31 lwiplib.h
-rw-r--r-- 1 root root 7843 Aug 14 18:39 lwipopts.h
-rwxr-xr-x 1 root root 7325 Aug 14 22:31 mmu.h
drwxr-xr-x 3 root root 4096 Aug 14 18:39 netif
drwxr-xr-x 3 root root 4096 Aug 14 18:39 posix
-rwxr-xr-x 1 root root 9848 Aug 14 22:31 soc_AM335x.h
ragu@ragu-ubuntu:~/work/gsoc/lwip/lwip-patch/rtems-source-builder$ ls -l /home/ragu/build_tools/rtems_latest/arm-rtems4.11/beagleboneblack/lwip/lib/
total 1796
-rw-r--r-- 1 root root 1641832 Aug 14 18:39 liblwip.a

-rw-r--r-- 1 root root  194594 Aug 14 22:31 liblwipdrv.a

4. Build the application
a. Clone the repo
    git clone https://github.com/ragunath3252/lwip-app.git

b. export RTEMS_MAKEFILE_PATH=path-to-your-installed-bsp-directory
     We need to set this variable so that the app can see where the libraries and header files are installed.

c. make

d. It will create the lwip.exe in o-optimize/lwip.exe

e. This is a elf executable. You can use this to boot your BBB

Now this app is configured to use DHCP. So it will get an ip address using DHCP and stops.
You can ping to the ip address and see the response.









In this post I will explain the necessary steps needed to port a ethernet driver from FreeBSD to rtems-libbsd.  There are few changes we need to make to be able to compile the driver.

I will be using cpsw ethernet driver for BBB as reference.  Follow the below steps
Whenever we edit a header file or c file, we need to add the changes under #if defined  __rtems__.
The code on FreeBSD needs to go under the #else part.

STEPS


1. Copy the driver files from FreeBSD to appropriate destination in rtems-libbsd
     I copied it to "freebsd/sys/arm/ti/cpsw"

2.  Include the added files in Makefile
     "LIB_C_FILES += freebsd/sys/arm/ti/cpsw/if_cpsw.c"

3.  Add the following header file for any c file you are including
     "#include <machine/rtems-bsd-kernel-space.h>"

4. At this stage, your driver is included for compilation. start compilation
    "make clean && make"

5. You will get several errors. You will need to resolve the errors one by one. The errors that come
     are dependent on the driver. I will explain some of the common errors.

Common Issues

     a.   Sysctl
          The FreeBSD driver usually add sysctls to get stats and adjust variables.  RTEMS do not
          support these. We need to remove all functions and variables related to sysctl handling.

     b.  OFW/FDT
          Open Firmware(OFW)/ Flattened Device Tree (FDT) dependency. FreeBSD supports FDT
          involves supplying device tree information during boot time using a special configuration file.
          RTEMS do not have this support yet, we need to remove those dependencies. Commonly they
          are seen in probe and attach functions

     c. In attach functions, we may get the phy address from FDT. This phy address is used during
         mii_attach. We can give MII_PHY_ANY in mii_attach. It will loop through all the possible
         addresses and will find the correct phy.

     4. There may some other dependencies on other drivers or some other modules which is defined
          FreeBSD but not needed in RTEMS. You can define equivalent functions as per the
          requirement. I defined my own functions to read the mac address.

Simplebus vs nexus

         RTEMS has a well defined nexus bus support. It will be the one that will be attaching to root and other drivers will be attaching to this bus. Simplebus interface is not present in RTEMS. Simplebus is usually the bus related to OFW interface. So when we have to port a driver based on simplebus we have two options

1. Port simplebus interface to rtems-libbsd
2. Modify the driver to nexus bus

I took the option to modify the bus to use the nexus bus.  For this you need to make the following changes

1. In the DRIVER_MODULE definition, we use nexus instead of simplebus
     
    #ifndef __rtems__
    DRIVER_MODULE(cpsw, simplebus, cpsw_driver, cpsw_devclass, 0, 0);
    #else  
    DRIVER_MODULE(cpsw, nexus, cpsw_driver, cpsw_devclass, 0, 0);
    #endif

2. Next thing we need to define the resource structure which will inform the driver the base address
     to be used for bus handles and irq to be used for the device. The resource should have the  
     following details the memory map address and the  irq and their numbers to be used by the 
     driver. Cpsw driver starts at 0x4a100000 and have 4 irq's starting at 40.
     

    #elif defined(LIBBSP_ARM_BEAGLE_BSP_H)

     static const rtems_bsd_device_resource cpsw0_res[] = {
        {
                .type = RTEMS_BSD_RES_MEMORY,
                .start_request = 0,
                .start_actual = 0x4a100000 /*Memory map address of the ethernet*/
        }, {
                .type = RTEMS_BSD_RES_IRQ,
                .start_request = 0,
                .start_actual = 0x28
        },
           {
                .type = RTEMS_BSD_RES_IRQ,
                .start_request = 1,
                .start_actual = 0x29
        },
           {
                .type = RTEMS_BSD_RES_IRQ,
                .start_request = 2,
                .start_actual = 0x2a
        },
           {
                .type = RTEMS_BSD_RES_IRQ,
                .start_request = 3,
                .start_actual = 0x2b
        }
};

3. Define the following macro below the resource structure
     RTEMS_BSD_DEFINE_NEXUS_DEVICE(cpsw, 0, RTEMS_ARRAY_SIZE(cpsw0_res),
    &cpsw0_res[0]);
     This is needed because, we use SYSINIT feature of FreeBSD. With this definition, we will be 
      automatically loaded during boot time. For more details see libbsd.txt file.

With these changes we moved to nexus bus. 

4. You may need to port the phy driver also from FreeBSD. For me I needed smscphy. So I added smscphy.c to rtems-libbsd and included it in compilation.

5. We need to make sure  the phy device get attached to miibus. for this we define 
     SYSINIT_DRIVER_REFERENCE(smscphy, miibus) in the same nexus device file.

With this we should be able to form a proper device tree.

LOG

Below is the log I got. Ignore the Failed to read PHY messages. Since we gave MII_PHY_ANY during attach, it tries different address so we getting failed messages

## Transferring control to RTEMS (at address 80000000) ...

RTEMS Beagleboard: am335x-based
*** LIBBSD INIT 1 TEST ***

RTEMS Shell on /dev/console. Use 'help' to list commands.
[/] # nexus0: <RTEMS Nexus device>
cpsw0: <3-port Switch Ethernet Subsystem> on nexus0
00:00:00 cpsw_attach
cpsw0: device parent is present
cpsw0: CPSW SS Version 1.12 (0)
cpsw0: Initial queue size TX=128 RX=384
cpsw0: MAC HI ce04a578
cpsw0: MAC Low f531
devctl: !system=IFNET subsystem=cpsw0 type=ATTACH
cpsw0: Ethernet address: -2144597976
cpsw0: Failed to read from PHY.
cpsw0: Failed to read from PHY.
cpsw0: Failed to read from PHY.
cpsw0: Failed to read from PHY.
cpsw0: Failed to read from PHY.
cpsw0: Failed to read from PHY.

miibus0: <MII bus> on cpsw0
smscphy0: <SMC LAN8710A 10/100 interface> PHY 0 on miibus0
smscphy0:  10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
devctl: +smscphy0 at phyno=0 oui=0x800f model=0xf rev=0x1 on miibus0
devctl: +miibus0 at   on cpsw0
devctl: +cpsw0 at   on nexus0
devctl: +nexus0 at   on root0
devctl: !system=IFNET subsystem=lo0 type=ATTACH


IRQ defined can be seen using irq command

[/] #  irq
-------------------------------------------------------------------------------
                             INTERRUPT INFORMATION
--------+----------------------------------+---------+------------+------------
 VECTOR | INFO                             | OPTIONS | HANDLER    | ARGUMENT
--------+----------------------------------+---------+------------+------------
     40 | cpsw0                            |  UNIQUE | 0x800d8788 | 0x802c5428
     41 | cpsw0                            |  UNIQUE | 0x800d8788 | 0x802c5460
     43 | cpsw0                            |  UNIQUE | 0x800d8788 | 0x802c5498
     67 | Clock                             |  UNIQUE | 0x800d7684 | 0x00000000
     72 | NS16550                       |  SHARED | 0x800d945c | 0x00000000
--------+----------------------------------+---------+------------+------------



     
In this post I will explain how to build rtems-libbsd for BeagleBoneBlack(BBB).

STEP 1:
Build rtems-master for beagleboneblack bsp. It will create the necessary libraries we need.
Pls refer to older posts on how to build rtems-master for BBB. We need to give an extra option during configure to tell where to install the built files. So the sequence of steps would be

1. ${HOME}/git-rtems/configure  --prefix=${HOME}/sandbox/install --target=arm-rtems4.11
        --enable-rtemsbsp=beagleboneblack
    Prefix can be any folder where you want to install the files. I am giving
    "/home/ragu/development/install"
2. make
3. make install

STEP 2:
1. Clone the rtems-libbsd repo
    https://github.com/RTEMS/rtems-libbsd
2.  Edit the config.inc file
     
# Mandatory: Select your BSP and installation prefix
TARGET = arm-rtems4.11
BSP = beagleboneblack
PREFIX = /home/ragu/development/install (The one we gave during rtems-master build)

# Optional: Separate installation base directory
INSTALL_BASE = $(PREFIX)/$(TARGET)/$(BSP)

# Optional: Network test configuration
TEST_RUNNER = $(BSP)
NET_CFG_SELF_IP = 10.117.83.42
NET_CFG_NETMASK = 255.255.255.0
NET_CFG_PEER_IP = 10.117.83.2
NET_CFG_GATEWAY_IP = 10.117.83.2
NET_TAP_INTERFACE = tap0

3. make clean

4. make

The built libraries can be found at testsuite directory.

RTEMS has a well defined networking support. In this post, I will give a overview of the networking in RTEMS and relevance to GSoC 2015

RTEMS users have two options for networking

1. libnetworking present in the RTEMS master
2.  libbsd based on FreeBSD network stack

Native Libnetworking:


           RTEMS master supports networking using libnetworking library. It can be enabled by "--enable-networking=yes" during configure. There are few config structures we need to define which will enable the network interface. More details are available in the RTEMS network supplement document

rtems-libbsd:


           RTEMS also supports a port of FreeBSD network stack known as "rtems-libbsd". It contains network stack based on FreeBSD 9.3. Applications use rtems base libraries and libbsd network stack.
It is present on a separate repo though it depends on rtems-master for bsp specific code. We can build applications by cloning this repo rtems-libbsd git 

How it works:

1. First we need to build rtems master to get the base libraries.
2. Then we need to install the built files in a directory which is used later. Required files and libraries      like librtemsbsp.a, librtemscpu.a etc are copied
3. We mention this path to rtems-libbsd 
4. Building rtems-libbsd will produce a libbsd.a that contains the object files of the network stack
5. Then applications are built using these libraries which can be found in testsuite directory

With this setup, there is no need to develop new drivers. We can easily port the drivers from FreeBSD. 

More details about rtems-libbsd can be obtained from libbsd.txt