Showing posts with label port. Show all posts
Showing posts with label port. Show all posts

Sunday, August 17, 2014

[GSoC 2014] Porting RTEMS to OpenRISC - Final report

It was a great Google Summer of Code instance this year for me working on a project of my interest (Porting RTEMS to OpenRISC), and achieved a good progress. In this post I will give some implementation details about the parts I worked on, and what has been done so far.

1. CPUKIT


The main low-level part of the OpenRISC CPU port goes there. The port provides configurations of the CPU there. All of the cpukit code I have written is now upstream. The following are the major parts of cpukit already implemented.

1.1 Utility


A new file called or1k-utility.h is added to contain great deal of OpenRISC specific information. Special purpose registers definitions and bit locations and masks within these registers are there. Also, some of the most frequently used functions like _OR1K_mfspr, and _OR1K_mtspr, power management are added. Most of OpenRISC/RTEMS .c files (e.g. BSP clock driver, interrupt handling, UART driver, etc) include this file.

1.2 Interrupt handling


New real-world interrupt handling scheme has been implemented to follow most of other RTEMS ports implementation. Interrupt handling now has stages to go through:

1.1.1 BSP: The very-early executed code starts from the BSP assembly code. Please see or1ksim BSP start.S section below for more details. Once an interrupt is raised, the PC jumps to a specific address at the BSP code, and from there it jumps to _ISR_Handler, a big chuck of assembly code located at cpukit port, and it's the core of interrupt handling.

1.1.2 _ISR_Handler: I consider this the core of interrupt handling for this port. This is a very critical code that needed to be implemented accurately. Initially, it allocates a new space in the interrupted task stack to save CPU_Exception_frame content. CPU_Exception_frame for OpenRISC is shown in the next figure.

CPU_Exception_frame


Once a new space is allocated in the stack, the task context is dumped there. Then nesting level is incremented, and thread dispatching is disabled. At this point, a decision must be made if it's needed to switch the stack to RTEMS SW interrupt stack depending on the nesting level. Once all of the previous actions have been done, the code would be ready to jump to the user C handler.

1.1.3 C Handler: This is the user C handler which can be installed dynamically. Initially, there are default handlers set by the BSP at the startup code. Later, a user can install a new C Handler by calling _CPU_ISR_install_vector(). An example quoted from the or1ksim clock driver, installing the C handler is followed.

or1ksim clock driver install ISR handler 




1.1.4 Restore exception context: After returning from the C handler, a check whether a thread dispatch is necessary, and if so, jump to _Thread_Dispatch. The final action is to restore the previously saved context and return from interrupt.

1.1.5 Default ISR Handler

This is a default ISR C handler that is installed for all interrupt types in the BSP vector table statically at startup code. Later, the code can install other C handlers with vector index if needed. The implementation of this default handler just calls rtems_fatal with exception error code, and CPU_Exception_frame. rtems_fatal in tern, halts the processor and print out the context frame if needed.

default or1k exception handler implementation



The following flowchart shows how interrupts are processed in RTEMS for OpenRISC. 

Flowchart of RTEMS/OpenRISC interrupt processing


1.3 Context Switch 


A major part of any operating system is context switch. This code simply dumps the task context of the currently executing task, and restore the context of the heir task to the processor state making it running. The OpenRISC port only saves/restore preserved registers across function calls.


1.4 cpu.h


This file is provided by every port. It contains CPU configurations, available features, stack growth direction, macros definition, inline functions, and other configurations and CPU specifications every port should provide. For example, enable/disable interrupts are implemented there.

Snippet code of or1k/rtems/cpu.h file



1.5 Power management


Although power management is optional HW feature, I added handling code for targets that supports it. As or1ksim is capable of simulating power management features (sleep mode), the IDLE task could make use of it by going into sleep mode instead of generic IDLE loop.

IDLE Thread body using power management sleep mode

1.6 Context initialize

 
Once a thread is created, its control structure needs to be initialized. The port should implement such a function. The initialization involves setting up the stack pointers, entry point and SR register. In future implementation, TLS and FP implementation support would take a role here.

Context initialize implementation



1.7 Exception frame print


This is a utility function that can be useful for dumping the content of the exception frame in a formatted way.

2. or1ksim BSP


or1ksim is the first BSP for the new OpenRISC port. It's intended to run on or1ksim (the main or1k emulator). It simulates great range of real hardware features. I have worked on implementing the most important parts that most BSPs provide.

2.1 Start.S


This file contains the very early executed code for or1ksim BSP. Once the program starts, a reset interrupt occurs, jumping to _start assembly function. _start is responsible for:


  1. Setup SR registers to Supervision mode.
  2. Load stack and frame pointers.
  3. Clear .bss area.
  4. Jump to boot_card.


It is also responsible for interrupts stuff, providing ISR vector table which contains addresses of user exception C handlers. Initially, this table is setup with default ISR Handler from cpukit (refer to the cpukit, interrupt handling section). Installing a new C handler involves writing to this table. 

or1ksim BSP vector table

Moreover, HW interrupts jump to arbitrary addresses, in which start.S provide generic prologue code that passes vector number to _ISR_Handler before jumping to it.


prologue exception handling instructions at start.S


2.2 Console driver 


Console driver is implemented to enable the BSP to emit some output characters to the console. Most RTEMS tests use console driver (printk, printf), to output some data regarding test results and to notice there behavior. The following figure is an output of running ticker.exe (one of RTEMS test samples) that use both console and clock drivers. It's running on or1ksim and attached to gdb. 

ticker.exe output


2.3 Clock driver


Clock driver is needed for any BSP/target that needs multi-tasking (i.e, context switch) and operating systems scheduling features. OpenRISC has only one timer called tick timer. The or1ksim BSP provides clock driver initialization that setup necessary registers, tick time, installing Clock_isr C handler, and enable tick timer interrupts. RTEMS uses tick timer restart mode, so when a tick interrupt occurs it restart itself and count from zero again. Also or1ksim clock driver implementation provides a function called or1ksim_clock_at_tick which is executed part of the RTEMS Clock_isr C handler to do HW specific actions. For OpenRISC, it just clears pending interrupts, setup the TTMR register again, and reset TTCR (timer counter) to zero (optional). Please note that or1ksim is not accurate regarding timing.

2.4 Timer benchmark


Simple timer benchmark driver is provided to run some tests that help profiling and calculating some performance statistics. It's mainly based on the clock driver.

3. toolchain


At early stages of the project, I had to work on the GNU toolchain to support building RTEMS for or1k targets. The work involved adding some configurations and modifying scripts to add or1k-rtems* and similar stuff. The following status of the toolchain is supplied at the time of this post was written. It may be changed later.

3.1 binutils


By now, OpenRISC folks pushed their new or1k support upstream to cvs and that included my work. So, binutils can be built for both or1k-elf and or1k-rtems* targets by cloning cvs target. This work would be included in the next binutils release (2.25?)

3.2 newlib 


I had to work on newlib library as it's used by RTEMS as the main embedded library instead of libgcc. We (RTEMS and OpenRISC communities) discussed about some licence issues, and RTEMS community took a decision to avoid the licence problem. The OpenRISC GPL newlib code might be rejected by sourceware, so, I had to provide a complete minimal port for OpenRISC/RTEMS to newlib. It's now upstream and can be built from RSB or manually. By doing that, we avoided the possibility that newlib from OpenRISC folks might be rejected. Later, when OpenRISC people want to push their code (after resolving these licence issues), they would have to adapt, modify, and add to my upstream code there.

3.3 gcc


OpenRISC community is working hard to push their gcc work upstream. I expect that to happen soon. I may be lucky enough to be one of the contributors of the early or1k gcc port when it's upstream.

3.4 gdb


gdb code (both OpenRISC and my RTEMS additions) may have to be delayed from being merged upstream. In the time being, or1k-rtems* toolchain is using a big bulk patch from my repository for building gdb7-7 release for or1k-rtems4.11-gdb. Hopefully, OpenRISC would push the code soon.

3.5 or1ksim


or1ksim can be built and run as described in OpenRISC instructions page. No additional work needed to run for RTEMS except sim.cfg, which is provided in my repo.

3.6 RSB


RSB (RTEMS Source Builder) is a great tool to build all the toolchain (i.e, binutils, newlib/gcc, gdb, or1ksim) from source on many platforms and operating systems. It's created and maintained by Chris Johns who mentored my this GSoC instance. I have added support for RSB to build the tools for or1k-rtems*-*. I am using Linux to build the toolchain, however, Chris stated recently that RSB can run on Windows, including the new or1k-rtems*-* toolchain.

References 

[1] RTEMS 

Wednesday, June 25, 2014

[HOWTO] build and run RTEMS on or1ksim

This post describes how to build, configure RTEMS to run on or1ksim emulator. Installing the tool-chain is a prerequisite before applying the steps in this post; if you have not already installed them, check out the steps here and do it. Once the tool-chain are installed and seen in the executable path, you may proceed with the following steps.

1- Set up the work space.

$ mkdir ~/rtems-dev
$ cd ~/rtems-dev

2- Clone my RTEMS project repo


This is temporary, by the end of the project, all the code at my repo should be upstreamed to RTEMS.

$ git clone git@github.com:heshamelmatary/rtems-gsoc2014.git
$ cd rtems-gsoc2014

3- Switch to or1k branch


I have created a branch for the project to help me with arranging and generating patches against master; meanwhile, keep master branch synchronized with remote.

$ git checkout or1k

4- bootstrap


$ bootstrap -p
$ bootstrap

5- Configuring and building 


$ cd ../
$ mkdir b-rtems
$ cd b-rtems
$ ../rtems-gsoc2014/configure --target=or1k-rtems4.11 --enable-rtemsbsp=or1k_or1ksim --disable-posix --disable-itron --disable-networking --disable-smp

You should get hello and ticker applications in their executable form. Other applications/tests will fail to compile because of other features/implementations that are not supported yet.

Running and debugging hello.exe


1- First you should have an or1ksim configuration script suitable for or1ksim BSP. This is the sim.cfg file I use at this stage of the project. It should be placed at your home directory. Note that as long as more features like: FP, cache manager, MMU manager are added, this file has to be changed to simulate these functionalists on or1ksim.

2- Run hello application on or1ksim.

The configuration file uses RSP (remote protocol) to enable GDB to connect to or1ksim. So, when running or1ksim, it reads configuration script, loads the program into the proper addresses, and waits for GDB to connect.

$ cd $HOME/rtems-dev/b-rtems/or1k-rtems4.11/c/or1k_or1ksim/testsuites/samples/hello/
$ or32-elf-sim -f ~/sim.cfg hello.exe

You should get something similar to the following picture:




3- Run GDB and connect to or1ksim 

From another terminal run GDB and connect to or1ksim

$ or1k-rtems4.11-gdb $HOME/rtems-dev/b-rtems/or1k-rtems4.11/c/or1k_or1ksim/testsuites/samples/hello/hello.exe

From gdb, attach it to or1ksim

(gdb) target remote :50001 
(gdb) continue

UART should emit the string output to or1ksim (and any other channel you provided in configuration script)




References 


Tuesday, June 24, 2014

[HOWTO] Build RTEMS tool-chain for OpenRISC targets

This post provides two methods of building RTEMS tool-chain for OpenRISC 1000 architecture: 1) building from RSB (RTEMS Source Builder) and 2) building each tool/program separately by downloading official tools' releases and apply our RTEMS specific patches to them. Merely, RSB is responsible for all the stuff including: setting up the environment, downloading releases, applying patches, configuring, building, and installing all the tools. The resulted tools should be program prefixed with or1k-rtems4.11-*. You may want to have a look at OpenRISC ELF GNU tool-chain; but note that RTEMS applications can't be built via these tools. The tool-chain has been tested and used on Fedora 20 and Ububtu 12.04 LTS. 

The tools/programs releases in the time being this post was written are:

  • binutils-2.24
  • gcc-4.8.2
  • newlib-2.1.0
  • gdb-7.7
  • or1ksim-github-head

Building RTEMS from RSB


Please have a look at RSB documentation here. It provides details in a thorough manner about RSB: how to download RSB, check environment, build RTEMS tool-chain for a specific target. Also, it gives a clear picture how RSB works internally.

1- Setup development and work space

$mkdir ~/rtems-dev
$cd ~/rtems-dev

2- Clone RSB 

$ git clone git://git.rtems.org/rtems-source-builder.git
$ cd rtems-source-builder

3- Check host environment


Check if host environment is setup correctly.
$ source-builder/sb-check
This command will tell you if any packages are required to be installed, if you miss any, please install them and try again, once every thing is Ok, you should have the following message:
$ source-builder/sb-check
RTEMS Source Builder environment is ok

 4- Building

$ cd rtems
$ ../source-builder/sb-set-builder --log=l-or1k.txt --prefix=$HOME/rtems-dev/rtems/4.11 \ 4.11/rtems-or1k

5- Check if all tools are installed successfully. You should get the following results


$ ls $HOME/rtems-dev/rtems/4.11
bin include lib libexec share or1k-rtems4.11
$ ls $HOME/development/rtems/4.11/bin
 

6- Add the newly installed tool-chain to the executable PATH

$ export PATH=$PATH:/$HOME/development/rtems/4.11/bin

Building RTEMS manually 

Currently, all or1k and RTEMS related patches are not upstreamed. So, we have to download official releases and apply patches to support or1k and RTEMS to them. I have worked on combining both or1k and RTEMS patches for all the tools against official tool releases. The following method of building the tools should be temporal. Eventually all patches including or1k and RTEMS should be upstreamed and tools should be built without patches provided here. 

1- Setup development and work space

$mkdir ~/rtems-dev
$cd ~/rtems-dev

2- Get the sources

3- Get the patches

Download all patches for the previous binutils, gcc, newlib, gdb releases from my repo; preferably, the latest patches (with respect to commit time). Put them in the same directory. 

4- Unpack archives 

$ tar xf binutils*.tar.* 
$ tar xf gcc*.tar.* 
$ tar xf newlib*.tar.* 
$ tar xf gdb*.tar.
*

5- Apply patches

$ cd binutils-2.24
$ cat ../binutils*.diff | patch -p1
$ cd ../gcc-4.8.2
$ cat ../gcc*.diff | patch -p1
$ cd ../newlib-2.1.0$ cat ../newlib*.diff | patch -p1
$ cd ../gdb-7.7
$ 
cat ../gdb*.diff | patch -p1
 $ cd ../ 

6- Configure and build tools


  • Create build directories for all the tools
$ mkdir b-binutils b-gcc b-gdb

  • Configure and build binutils
$ cd b-binutils
$ ../binutils-2.24/configure --target=or1k-rtems4.11 --prefix=$HOME/rtems-dev/rtems/4.11
$ make
$ make install

  • Setup the PATH to include binutils binaries 
$ export PATH=$PATH:/$HOME/rtems-dev/rtems/4.11/bin

  • Link newlib into gcc directory
$ cd ../gcc-4.8.2/
$ ln -s ../newlib-2.1.0/newlib .

  • Configure and build gcc and newlib
$ cd ..
$ cd b-gcc
$ ../gcc-4.8.2/configure --target=or1k-rtems4.11 --prefix=$HOME/rtems-dev/rtems/4.11 --with-gnu-as --with-gnu-ld --enable-languages="c,c++" --enable-threads --disable-libssp --with-newlib --with-system-zlib --disable-libstdcxx-pch --disable-nls --without-included-gettext --disable-win32-registry --disable-lto --enable-newlib-io-c99-formats
$ make 
$ make install
  • Configure and build gdb
$ cd ../
$ cd b-gdb$ ../gdb-7.7/configure --target=or1k-rtems4.11 \
--prefix=$HOME/rtems-dev/rtems/4.11 \
--verbose --disable-nls \
--without-included-gettext \
--disable-win32-registry \
--disable-werror \
--disable-sim} \
--without-zlib \
--with-expat \
--with-python} \
--prefix=$HOME/rtems-dev/rtems/4.11

Building or1ksim

You can follow instructions here to build and configure OpenRISC simulator- or1ksim. Patch for building or1ksim from RSB is on its way to be commited soon.

Monday, April 21, 2014

[GSoC] Porting RTEMS to OpenRISC - Introduction

This year (2014) I’m participating in GSoC program with RTEMS. The project—Porting RTEMS to OpenRISC— (as its name indicates) aims to port RTEMS to OpenRISC architecture. Porting a well-known open source RTOS software like RTEMS for a big open source hardware architecture such as OpenRISC would be of useful to both HW and SW communities. The new port will target a broad range of users and fields (hobbyists, digital designers, computer architecture, embedded systems, industrial applications, etc).

In order to have a successful long term RTEMS port for OpenRISC that people can use, there are main goals (increments) to achieve during the project:

1- Integrate OpenRISC toolchain into RTEMS

To be able to compile and build RTEMS for OpenRISC architecture, some tools need to be added to RTEMS toolchain first. OpenRISC has its own tool-chain independent of RTEMS. So, the job would involve integrating both OpenRISC and RTEMS tool-chain, and make the necessary modifications/additions that fit for RTEMS. These tools include:
  • binutils
  • gdb
  • newlib 
  • gcc
  • RSB (RTEMS Source Builder)

2- Porting low-level pieces of RTEMS

This includes writing start assembly, device drivers, interrupt handlers, context save, etc. The main components in RTEMS which this goal have to deal with are:

score/cpu: To define general/common OpenRISC architecture's functions.
libcpu (optional): To contain cache and MMU managers.
libbsp: BSPs code.

3- Writing a BSP for a board that OpenRISC supports

A simple BSP that can run hello world and ticker would be needed to be a front-end interface to OpenRISC and RTEMS users. Two BSPs can implemented:

openrisc_or1ksim: This BSP should be for simulation and debugging purposes only.
openrisc_atlys: I have Atlys board which can be used during the project to be the first OpenRISC BSP on RTEMS. Atlys is supported by OpenRISC and libgloss port and can run linux kernel.

4- Setup simulators and debuggers for OpenRISC.

This task includes writing sim-scripts to use openrisc or1k tools, simulators, debuggers. Software and hardware debugging should supported at this stage.

Environment 

  • Platform: Fedora 20 and Ubuntu 12.04 LTS.
  • Toolchain: Latest toolchain for OpenRISC.
  • Simulators: or1ksim and/or qemu.
  • Debuggers: gdb connected to or1ksim (OpenRISC tools). Also I should be debugging at real HW (Atlys board) by gdb via JTAG channel.
  • Hardware: Atlys FPGA board (supported by OpenRISC).

If you are interested, I should be posting any updates for the project here in my blog. Also, you may want to have a look at project source code at my github account. Project link at RTEMS also exists.