Skip to content

Commit

Permalink
doc: Completely reworked EMSK section
Browse files Browse the repository at this point in the history
* Add links to useful extrenal resources.
* Simplified guides.
* Fixed a guide for building with support of UART.
  • Loading branch information
kolerov committed Jun 24, 2024
1 parent 1a7a0bc commit cf3f6df
Showing 1 changed file with 100 additions and 106 deletions.
206 changes: 100 additions & 106 deletions doc/baremetal/em-starter-kit.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,64 @@
Using GNU Toolchain to Debug Applications on EM Starter Kit
===========================================================

To learn how to build and debug application using Eclipse IDE, please use
:doc:`../ide/index` manual.

You can find all necessary information about configuring the board and
connecting to UART in a User Guide which is published in
`ARC EM Starter Kit section <https://github.com/foss-for-synopsys-dwc-arc-processors/ARC-Development-Systems-Forum/wiki/ARC-Development-Systems-Forum-Wiki-Home#arc-em-starter-kit-1>`_
on ARC Development Systems Forum.

Prerequisites
-------------

Toolchain for Linux and Windows hosts can be downloaded from the `GNU Toolchain
Releases page
<https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/releases>`_.
For Linux hosts there is a choice between complete tarballs that include
toolchain, IDE and OpenOCD (like installer for Windows), and tarballs that
include toolchain only.
A toolchain for Linux and Windows hosts can be downloaded from the `GNU Toolchain
Releases page <https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/releases>`_.
OpenOCD for debugging applications on hardware boards is shipped with IDE bundle only.
OpenOCD binary (``openocd`` for Linux and ``openocd.exe`` for Windows) resides in ``bin`` directory of IDE.

In order to use OpenOCD on Windows it is required to install appropriate WinUSB drivers,
see :doc:`../ide/how-to-use-openocd-on-windows` for details.
Download and install Digilent Adept `runtime and utilities <https://digilent.com/shop/software/digilent-adept/download>`_
to be able to work with EM Starter Kit on Linux. In order to use OpenOCD on Windows it is required to install
appropriate WinUSB drivers, see :doc:`../ide/how-to-use-openocd-on-windows` for details.


Building an application
-----------------------
Building a Simple Application
-----------------------------

To learn how to build and debug application with Eclipse IDE, please use
:doc:`../ide/index` manual.
Consider this simple application (assume that it's saved in ``main.c``):

.. code-block:: c
int main()
{
return 0;
}
Different core templates in EM Starter Kit use different memory maps.
It means that you need to use a special memory map file with ``.x`` extension
to be able to compile and run your application on EM Starter Kit.

In first, clone `toolchain <https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain>`_
repository and look into ``extras/dev_systems`` directory. This directory contains
memory map files for different boards and cores. For example, ``sk2.3_em7d.x``
is a memory map file for EM7D core of EM Starter Kit 2.3. You need to put that memory map
file to the current directory, rename it to ``memory.x`` and use ``-Wl,-marcv2elfx``
option while compiling your application. Please refer to :doc:`linker` for more details
about ``memory.x`` files.

Different core templates in EM Starter Kit use different memory maps, so
different memory map files are required to compile applications that work
properly on those configurations. This "toolchain" repository includes memory
maps for all supported EM Starter Kit versions and configurations. They can be
found at
https://github.com/foss-for-synopsys-dwc-arc-processors/toolchain/tree/arc-staging/extras/dev_systems
Memory map files in that directory have ``.x`` extension and file to be used
should be renamed to ``memory.x``, because ``arcv2elfx`` linker emulation
doesn't support ability to override that file name. Please refer to
:doc:`linker` for more details about ``memory.x`` files.
That is how we compile the application for EM7D core of EM Starter Kit 2.3::

For example for EM Starter Kit v2.3 EM7D to build an application::
cp -a toolchain/extras/dev_systems/sk2.3_em7d.x memory.x
arc-elf32-gcc -g -Wl,-marcv2elfx -specs=nosys.specs -mcpu=em4_dmips main.c -o main.elf

$ cp -a toolchain/extras/dev_systems/sk2.3_em7d.x memory.x
$ arc-elf32-gcc -Wl,-marcv2elfx --specs=nosys.specs -mcpu=em4_dmips -O2 -g \
test.c -o test.elf
We use ``libnosys`` (``--specs=nosys.specs``) her to force standard IO functions
to do nothing - they will set ``errno = ENOSYS`` and return -1 in most cases.

.. table:: List of compiler flags corresponding to particular CPUs
You need to use correct ``-mcpu`` and other additional options for building your
application for particular board and core. You can find all necessary options
for any EM Starter Kit configuration in this table:

.. table::

+------+--------+------------------------------------------------------------+
|EM SK | CPU | Flags |
Expand Down Expand Up @@ -78,41 +98,43 @@ For example for EM Starter Kit v2.3 EM7D to build an application::
| | EM11D | -mcpu=em4_fpuda -mfpu=fpuda_all |
+------+--------+------------------------------------------------------------+

Building an Application With Support of UART
--------------------------------------------

Consider this application (assume that it's saved in ``hello.c``):

C library for GNU Toolchain for ARC provides basic support for UART module of EM
Starter Kit, which allows to use standard C function for input and output:
``printf()``, ``scanf()``, etc. Memory map files are also provided for processor
configurations of EM Starter Kit. Both of those features are available via
special "specs" files: ``emsk_em9d.specs`` and ``emsk_em11d.specs`` (there is no
separate file for EM7D of EM Starter Kit, it is identical to EM9D). Usage
example is following::
.. code-block:: c
$ cat hello_world.c
#include <stdio.h>
int main() {
printf("hello world\n");
return 0;
}
#include<stdio.h>
$ arc-elf32-gcc --specs=emsk_em9d.specs -mcpu=em4_dmips hello_world.c
int main()
{
printf("Hello, World!\n");
return 0;
}
Note that it is still required to specify valid ``-mcpu`` option value - it is
not set by the specs file.
You need to use ``emsk_em9d.specs`` (for EM7D or EM9D) or ``emsk_em11d.specs``
(for EM11D) specs files instead of ``nosys.specs`` to enable support of UART.
It allows using standard C function for input and output: ``printf()``, ``scanf()``,
etc.

That is how we compile the application for EM7D core of EM Starter Kit 2.3::

cp -a toolchain/extras/dev_systems/sk2.3_em7d.x memory.x
arc-elf32-gcc -g -Wl,-marcv2elfx -specs=emsk_em9d.specs -mcpu=em4_dmips main.c -o main.elf

Running an application with OpenOCD
-----------------------------------

OpenOCD is used for connecting to development boards, running a GDB
server and loading programs to the boards using GDB.

Starting OpenOCD
^^^^^^^^^^^^^^^^

Parameters of a particular target board are described in the OpenOCD
configuration files. OpenOCD repository from Synopsys already includes several
configuration files made specifically for Synopsys own development platforms:
ARC EM Starter Kit and ARC SDP. Due to differences between different versions
of ARC EM Starter Kit hardware, there are separate configuration files for
different ARC EM Starter Kit versions:
OpenOCD uses configuration files for describing different boards. OpenOCD
is shipped with different configuration files for different EM Starter Kit
versions:

* ``snps_em_sk_v1.cfg`` - for ARC EM Starter Kit v1.x.
* ``snps_em_sk_v2.1.cfg`` - for ARC EM Starter Kit versions 2.0 and 2.1.
Expand All @@ -121,66 +143,52 @@ different ARC EM Starter Kit versions:
* ``snps_em_sk.cfg`` - this is a configuration for ARC EM Starter Kit 2.0 and
2.1, preserved for compatibility.

Following documentation would assume the usage of the latest ARC EM Starter Kit
version 2.3 which is similar to 2.2.
Assume that EM Starter Kit 2.3 is used. If you've downloaded IDE bundle for
Linux then you can run OpenOCD this way (replace ``<ide>`` by a path to
the directory of IDE bundle)::

Start OpenOCD::
<ide>/bin/openocd -s <ide>/share/openocd/scripts -c 'gdb_port 49101' -f board/snps_em_sk_v2.3.cfg

# On Linux (for manually built OpenOCD):
$ openocd -c 'gdb_port 49101' -f board/snps_em_sk_v2.3.cfg
If you've built and installed OpenOCD manually then you can run OpenOCD this way::

# On Linux (for prebuilt OpenOCD from IDE package):
$ $ide_dir/bin/openocd -s $ide_dir/share/openocd/scripts \
-c 'gdb_port 49101' -f board/snps_em_sk_v2.3.cfg
openocd -c 'gdb_port 49101' -f board/snps_em_sk_v2.2.cfg

@rem on Windows:
> openocd -s C:\arc_gnu\share\openocd\scripts -c "gdb_port 49101" ^
-f board\snps_em_sk_v2.3.cfg
If you've downloaded and installed IDE bundle for Windows then you can run OpenOCD this way:

OpenOCD will be waiting for GDB connections on TCP port specified as an
argument to ``gdb_port`` command, in this example it is 49101. When
``gdb_port`` command hasn't been specified, OpenOCD will use its default port,
which is 3333, however this port might be already occupied by some other
software. In our experience we had a case, where port 3333 has been occupied,
however no error messages has been printed but OpenOCD and GDB wasn't printing
anything useful as well, instead it was just printing some ambiguous error
messages after timeout. In that case another application was occupying TCP port
only on localhost address, thus OpenOCD was able to start listening on other IP
addresses of system, and it was possible to connect GDB to it using that
another IP address. Thus it is recommended to use TCP ports which are unlikely
to be used by anything, like 49001-49150, which are not assigned to any
application.

OpenOCD can be closed by CTRL+C. It is also possible to start OpenOCD from Eclipse
as an external application.
.. code-block:: winbatch
openocd -s C:\arc_gnu\share\openocd\scripts -c "gdb_port 49101" -f board\snps_em_sk_v2.3.cfg
OpenOCD will be waiting for GDB connections on TCP port specified as an
argument to ``gdb_port`` command (49101 in our case). If ``gdb_port`` is not
passed then the default port 3333 is used. It's recommended not to use a default
port since it may be occupied by another application. OpenOCD can be closed by CTRL+C.

Connecting GDB to OpenOCD
^^^^^^^^^^^^^^^^^^^^^^^^^

Write a sample application:
Write a sample application and save it to ``simple.c``:

.. code-block:: c
/* simple.c */
int main(void) {
int a, b, c;
a = 1;
b = 2;
c = a + b;
return c;
}
int main()
{
int a = 1;
int b = 2;
int c = a + b;
return c;
}
Build the application for EM7D core of EM Starter Kit 2.3::

Compile it - refer to "Building application" section for details, creation of
``memory.x`` is not shown in this example::
cp -a toolchain/extras/dev_systems/sk2.3_em7d.x memory.x
arc-elf32-gcc -g -Wl,-marcv2elfx -specs=nosys.specs -mcpu=em4_dmips main.c -o main.elf

$ arc-elf32-gcc -Wl,-marcv2elfx --specs=nosys.specs -mcpu=em4_dmips -O2 -g \
simple.c -o simple_sk2.3_em7d.elf
Start OpenOCD as it described earlier and start GDB, connect to target and run it:

Start GDB, connect to target and run it::
.. code-block:: text
$ arc-elf32-gdb --quiet simple_sk2.1_em5d.elf
$ arc-elf32-gdb -quiet main.elf
# Connect. Replace 3333 with port of your choice if you changed it when starting OpenOCD
(gdb) target remote :3333
# Increase timeout, because OpenOCD sometimes can be slow
Expand All @@ -199,25 +207,11 @@ Start GDB, connect to target and run it::
# For example, check exit code of application
(gdb) info reg r0
Execution should stop at function ``exit``. Value of register ``r0`` should be
``3``.

Execution should stop at function ``exit``. Value of register ``r0`` should be ``3``.

Known issues and limitations
----------------------------

* Out of the box it is impossible to perform any input/output operations, like
printf, scanf, file IO, etc.

* When using an nSIM hostlink (GCC option ``--specs=nsim.specs``), calling
any of those function in application will result in a hang (unhandled
system call to be exact).
* When using libnosys (``--specs=nosys.specs``), standard IO functions will
simply do nothing - they will set ``errno = ENOSYS`` and return -1 at most.
* It is possible to use UART for text console I/O operations, but that is
not implemented by default in GNU toolchain. Consult EM Starter Kit
documentation and examples for details.

* Bare metal applications has nowhere to exit, and default implementation of
exit is an infinite loop. To catch exit from application you should set
breakpoint at function ``exit`` like in the example.
Expand Down

0 comments on commit cf3f6df

Please sign in to comment.