0% found this document useful (0 votes)
164 views

OpenWrt SDK

The document discusses several ways to compile applications for OpenWrt targets using either a prebuilt OpenWrt toolchain or SDK. It provides steps to download and use a prebuilt toolchain to cross compile "hello world" examples. It also describes how to build OpenWrt packages using a prebuilt SDK, and how to debug programs using GDB locally or remotely.

Uploaded by

SailajaUngati
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
164 views

OpenWrt SDK

The document discusses several ways to compile applications for OpenWrt targets using either a prebuilt OpenWrt toolchain or SDK. It provides steps to download and use a prebuilt toolchain to cross compile "hello world" examples. It also describes how to build OpenWrt packages using a prebuilt SDK, and how to debug programs using GDB locally or remotely.

Uploaded by

SailajaUngati
Copyright
© © All Rights Reserved
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 10

[[PageOutline]]

= Building applications for an OpenWrt Target =


There are several ways you can use an OpenWrt Software Development Kit (SDK) or
Toolchain to compile your own applications outside of the OpenWrt buildroot :
* use prebuilt OpenWrt toolchain to build applications (ie from
http://dev.gateworks.com/openwrt/latest/)
* use prebuilt OpenWrt SDK to build an OpenWrt package (ie from
http://dev.gateworks.com/openwrt/latest/)
* use toolchain in your OpenWrt buildroot staging_dir tree (what you may need to
do if your running your own firmware with a different lib/kernel config than
Gateworks pre-built images)

The point of using the OpenWrt toolchain or SDK is that it can be pre-built and
installed on a host that does not have the OpenWrt buildroot.

Note: Custom programming can be achieved through shell scripts on the Gateworks
boards (most examples on the Gateworks wiki are shell commands). C code can be
used when desired.

== OpenWrt Prebuilt Toolchain ==


If you are using pre-built firmware from http://dev.gateworks.com/openwrt then you
can use the pre-built toolchain there to build your own code.

The steps involved:


1. Download prebuilt toolchain/SDK, the toolchain contains the compiler and
standard libraries only.
1. Uncompress it.
1. Add it to your path (optional)
1. Use the toolchain cross compiler to cross compile your code.

Examples:
* Example, if you wanted to build a hello-world for OpenWrt 14.08 for the laguna
(cns3xxx) platform:
{{{#!bash
$ wget http://dev.gateworks.com/openwrt/14.08/cns3xxx/OpenWrt-Toolchain-cns3xxx-
for-arm_v6k-gcc-4.6-linaro_uClibc-0.9.33.2_eabi.tar.bz2
$ tar xvf OpenWrt-Toolchain-cns3xxx-for-arm_v6k-gcc-4.6-linaro_uClibc-
0.9.33.2_eabi.tar.bz2
$ PATH=$PWD/OpenWrt-Toolchain-cns3xxx-for-arm_v6k-gcc-linaro_uClibc-
0.9.32_eabi/toolchain-arm_v6k_gcc-linaro_uClibc-0.9.32_eabi/bin:$PATH
$ cat << EOF > hello-world.c
#include <stdio.h>

int main (int argc, char** argv)


{
printf("Hello World\n");
return 0;
}
EOF
$ arm-openwrt-linux-uclibcgnueabi-gcc hello-world.c -o hello-world
$ file hello-world
hello-world: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked
(uses shared libs), not stripped
}}}
* Example OpenWrt 16.02 for the Ventana (imx6) platform:
{{{#!bash
# download toolchain
wget http://dev.gateworks.com/openwrt/16.02/imx6/Gateworks-Toolchain-imx6_gcc-
5.2.0_musl-1.1.12_eabi.Linux-x86_64.tar.bz2
# extract toolchain
tar xvf Gateworks-Toolchain-imx6_gcc-5.2.0_musl-1.1.12_eabi.Linux-x86_64.tar.bz2
# add toolchain to path
PATH=$PWD/Gateworks-Toolchain-imx6_gcc-5.2.0_musl-1.1.12_eabi.Linux-
x86_64/toolchain-arm_cortex-a9+neon_gcc-5.2.0_musl-1.1.12_eabi/bin:$PATH
# create a simple program
cat << EOF > hello-world.c
#include <stdio.h>

int main (int argc, char** argv)


{
printf("Hello World\n");
return 0;
}
EOF
# compile your program
arm-openwrt-linux-gcc hello-world.c -o hello-world
}}}

Note: The prebuilt toolchain may have some issue if the script arm-openwrt-linux-
uclibcgnueabi-wrapper.sh is used (with regard to paths having whitespace).

=== Ventana Notes ===


If desired, download the Ventana OpenWrt Toolchain/SDK and skip to step 4:
https://www.gateworks.com/download/gateworks-openwrt-16-02_20160520-sdk-imx6-tar-
bz2/
* [https://www.gateworks.com/download/gateworks-openwrt-16-02_20160520-sdk-imx6-
tar-bz2/ Gateworks-OpenWrt-16.02_20160520-SDK-imx6.tar.bz2]
(sha256sum:cb5868daeeafddd5032f0f0380654e5a736530aa1033ae9a8df3b54e77da2ea3)
* [https://www.gateworks.com/download/gateworks-openwrt-16-02_20160520-toolchain-
imx6/ Gateworks-OpenWrt-16.02_20160520-Toolchain-imx6.tar.bz2]
(sha256sum:7098d70fa5ab4d9be91d95261cd2d9552259043520711aa1f893bd8e4b4c9334)

1. Turn on Toolchain in make menuconfig -> Build the OpenWrt based Toolchain
2. Compile using make -j8 v=99 in trunk directory
3. Find compiled toolchain in trunk/bin/imx6/OpenWrt-Toolchain-imx6-for-arm_cortex-
a9+neon-gcc-4.6-linaro_uClibc-0.9.33.2_eabi.tar.bz2
4. Download the toolchain to a different directory on your PC where you will want
to do some compiling, such as ~/compiling
5. Extract the toolchain
{{{
ryan@Ryan:~/Documents/toolchain$ tar xvf OpenWrt-Toolchain-imx6-for-arm_cortex-
a9+neon-gcc-4.6-linaro_uClibc-0.9.33.2_eabi.tar.bz2
OpenWrt-Toolchain-imx6-for-arm_cortex-a9+neon-gcc-4.6-linaro_uClibc-0.9.33.2_eabi/
OpenWrt-Toolchain-imx6-for-arm_cortex-a9+neon-gcc-4.6-linaro_uClibc-
0.9.33.2_eabi/LICENSE
OpenWrt-Toolchain-imx6-for-arm_cortex-a9+neon-gcc-4.6-linaro_uClibc-
0.9.33.2_eabi/toolchain-arm_cortex-a9+neon_gcc-4.6-linaro_uClibc-0.9.33.2_eabi/
OpenWrt-Toolchain-imx6-for-arm_cortex-a9+neon-gcc-4.6-linaro_uClibc-
0.9.33.2_eabi/toolchain-arm_cortex-a9+neon_gcc-4.6-linaro_uClibc-
0.9.33.2_eabi/lib64
OpenWrt-Toolchain-imx6-for-arm_cortex-a9+neon-gcc-4.6-linaro_uClibc-
0.9.33.2_eabi/toolchain-arm_cortex-a9+neon_gcc-4.6-linaro_uClibc-
0.9.33.2_eabi/share/
......
.....
}}}
6. Set PATH
{{{
ryan@Ryan:~/Documents/toolchain$ PATH=$PWD/OpenWrt-Toolchain-imx6-for-arm_cortex-
a9+neon-gcc-4.6-linaro_uClibc-0.9.33.2_eabi/toolchain-arm_cortex-a9+neon_gcc-4.6-
linaro_uClibc-0.9.33.2_eabi/bin:$PATH
}}}
7. Create hello-world.c file as shown above,
8. Compile hello-world.c. Note, when compiling, Gateworks uses hard float, so you
may have to specify -mfloat-abi=hard as shown below
{{{
ryan@Ryan:~/Documents/toolchain$ arm-openwrt-linux-uclibcgnueabi-gcc -mfloat-
abi=hard hello-world.c -o hello-world
arm-openwrt-linux-uclibcgnueabi-gcc.bin: warning: environment variable
'STAGING_DIR' not defined
arm-openwrt-linux-uclibcgnueabi-gcc.bin: warning: environment variable
'STAGING_DIR' not defined
arm-openwrt-linux-uclibcgnueabi-gcc.bin: warning: environment variable
'STAGING_DIR' not defined
/home/ryan/Documents/toolchain/OpenWrt-Toolchain-imx6-for-arm_cortex-a9+neon-gcc-
4.6-linaro_uClibc-0.9.33.2_eabi/toolchain-arm_cortex-a9+neon_gcc-4.6-linaro_uClibc-
0.9.33.2_eabi/bin/../lib/gcc/arm-openwrt-linux-uclibcgnueabi/4.6.4/../../../../arm-
openwrt-linux-uclibcgnueabi/bin/ld: warning: .init_array section has zero size
ryan@Ryan:~/Documents/toolchain$
}}}
9. Verify hello-world has been compiled in current directory
{{{
ryan@Ryan:~/Documents/toolchain$ file hello-world
hello-world: ELF 32-bit LSB executable, ARM, version 1 (SYSV), dynamically linked
(uses shared libs), not stripped
}}}

== OpenWrt Prebuilt SDK ==


If you are using pre-built firmware from http://dev.gateworks.com/openwrt then you
can use the pre-built SDK there to build OpenWrt packages. The SDK contains a
cross toolchain, libraries, and the Makefile structure to be able to build OpenWrt
packages without having an entire buildroot tree. Note that you must also have the
OpenWrt Toolchain (see below) in your path. For example to build the OpenWrt
nuttcp package for laguna (cns3xxx):
{{{
$ wget http://dev.gateworks.com/openwrt/latest/cns3xxx/OpenWrt-SDK-cns3xxx-for-
linux-x86_64-gcc-4.6-linaro_uClibc-0.9.33.2.tar.bz2
$ tar xvf OpenWrt-SDK-cns3xxx-for-Linux-i686-gcc-linaro_uClibc-0.9.32.tar.bz2
$ PATH=$PWD/OpenWrt-SDK-imx61-for-linux-x86_64-gcc-4.6-linaro_uClibc-
0.9.33.2/staging_dir/toolchain-arm_v7-a_gcc-4.6-linaro_uClibc-0.9.33.2_eabi/bin:
$PATH
$ cd OpenWrt-SDK-imx61-for-linux-x86_64-gcc-4.6-linaro_uClibc-0.9.33.2
$ svn export svn://svn.openwrt.org/openwrt/packages/net/nuttcp package/nuttcp
$ make package/nuttcp/compile
$ ls bin/cns3xxx/packages/
nuttcp_6.1.2-2_cns3xxx.ipk nuttcp-xinetd_6.1.2-2_cns3xxx.ipk
}}}

== GDB - GNU Debugger ==

GDB can be used on Gateworks SBC's.

Gateworks has tested GDB in the following way on OpenWrt:


1. Compile GDB as a package using the make menuconfig option. Be sure it is GDB and
not GDB server (example shows GDB server):
[wiki:OpenWrt/Configuration#TurningonGDBServer]
2. Install the ipk file on the target board: [wiki:ipkupload]
3. Compile your program using the toolchain described above but with GDB support.
Example is hello-world.
{{{
arm-openwrt-linux-uclibcgnueabi-gcc -g -mfloat-abi=hard hello-world.c -o hello-
world
}}}
4. Copy program to target board and be sure it is executable (chmod)
5. Start gdb on target board (Ventana)
6. Run the gdb command from the Ventana command prompt:
{{{
(gdb) file hello-world
Load new symbol table from "/hello-world"? (y or n) y
Reading symbols from /hello-world...done.
}}}
7. Then type the run command:
{{{
(gdb) run
Starting program: /hello-world
warning: Unable to find dynamic linker breakpoint function.
GDB will be unable to debug shared library initializers
and track explicitly loaded dynamic code.
warning: no loadable sections found in added symbol-file /lib/libgcc_s.so.1
warning: no loadable sections found in added symbol-file /lib/libc.so.0
Hello World
[Inferior 1 (process 17906) exited normally]
}}}
8. For more GDB reference please see this page:
[http://www.gnu.org/software/gdb/documentation/ GDB Documentation] and other
examples on Google search.

=== Remote Debugging ===


A brief example:

1. From the target start the server using the command to use over TCP on port 2345
the application hello-world
{{{
root@OpenWrt:/# gdbserver host:2345 hello-world
}}}

Example Continues to step 2 below, shown below is the rest of the output:
{{{
root@OpenWrt:/# gdbserver host:2345 hello-world
Process hello-world created; pid = 21696
Listening on port 2345
Remote debugging from host 192.168.1.22
Hello World

Child exited with status 0


GDBserver exiting
root@OpenWrt:/#
}}}

2. From the host start the GDB from the SDK (Ventana example shown)
{{{
ryan@Ryan:~/sdk_ventana/OpenWrt-SDK-imx6-for-linux-x86_64-gcc-4.8-linaro_uClibc-
0.9.33.2$ ./staging_dir/toolchain-arm_cortex-a9+neon_gcc-4.8-linaro_uClibc-
0.9.33.2_eabi/bin/arm-openwrt-linux-uclibcgnueabi-gdb
}}}
3. Attach to target:
{{{
(gdb) target remote 192.168.1.1:2345
Remote debugging using 192.168.1.1:2345
0x76ff1e38 in ?? ()
(gdb)
}}}
4. Use the continue command and notice the program run on the target as shown in
step 1
{{{
(gdb) continue
Continuing.
Cannot access memory at address 0x0
[Inferior 1 (process 23862) exited normally]
(gdb)

}}}

== Using Toolchain from staging_dir ==


If you are running firmware from your own OpenWrt build directory you can use the
toolchain provided there. The OpenWrt toolchain is placed in staging_dir under a
directory name appropriate for your target configuration (toolchain-<arch-info>)
and you can use it there to build applications for your target directly without
using the buildroot:
* laguna - staging_dir/toolchain-arm_v6k_gcc-linaro_uClibc-0.9.32_eabi

Examples:
* Cross-compile hello-world.c for Ventana (imx6) using the OpenWrt 16.02, built in
the present working directory:
{{{#!bash
export STAGING_DIR=$PWD/staging_dir
export PATH=$STAGING_DIR/toolchain-arm_cortex-a9+neon_gcc-5.2.0_musl-
1.1.12_eabi/bin:$PATH
arm-openwrt-linux-gcc hello-world.c -o hello-world
}}}
* Cross-compile hello-world.c for Laguna (cns3xxx) using the OpenWrt 14.08, built
in the present working directory:
{{{#!bash
export STAGING_DIR=$PWD/staging_dir
export PATH=$STAGING_DIR/toolchain-arm_v6k_gcc-linaro_uClibc-0.9.32_eabi/bin:$PATH
arm-openwrt-linux-uclibcgnueabi-gcc hello-world.c -o hello-world
}}}

= Other Notes =
* uclibc is missing certain things that glibc on your desktop has - There really
isn't a clear list of what those items are.

* uclibc isn't your only libc option - OpenWrt has support for other popular
alternatives to glibc as well (make menuconfig, Advanced configuration options ->
Toolchain Options -> C Library implementation).

* Current OpenWrt (ie using our trunk BSP) supports uClibc (default) as well as
eglibc and musl.
* Note that eglibc is extremely popular and I believe Ubuntu has even switched to
using it.
* If you are missing features in the c++ lib then you can instead/also choose an
alternative to uClibc++ via menuconfig 'Global build settings -> Preferred standard
C++ library.
* In the toolchain/bin directory, there is a gcc-uc script which sets everything
up for uclibc++.
* c++ exceptions have special configuration as noted here
[http://lists.uclibc.org/pipermail/uclibc-cvs/2012-May/030326.html]

* Also, if you want to use compiler tools such as 'nm' you need to use the ones
from the cross toolchain (ie arm-openwrt-linux-nm)

* The STAGING_DIR may need to be set as noted here:


[http://wiki.openwrt.org/doc/devel/crosscompile]

= Additional Resources =

=== OpenWrt ===


OpenWrt is a open source software. There are many OpenWrt resources around the
web.[[BR]]
Open WRT Wiki for Cross Compile: [http://wiki.openwrt.org/doc/devel/crosscompile]
[[BR]]
OpenWrt Buildroot : [http://wiki.openwrt.org/doc/howto/buildroot.exigence]
OpenWrt Creating Packages : [http://wiki.openwrt.org/doc/devel/packages]

=== Other C code examples: ===

A userspace daemon has been written by Gateworks, source code is available[[BR]]


[http://trac.gateworks.com/wiki/gsc#GSCuserspaceDaemon]
[[BR]][[BR]]
[[BR]][[BR]]
Another small sample C program to read through input registers such as temp and
voltage on the Gateworks GSC
[http://trac.gateworks.com/wiki/gsc#SystemTemperatureandVoltageMonitor]

Steps:
1. Write the C code as a .c file such as input.c
2. Compile the C code with the instructions above
3. Transfer the resulting executable over to the Gateworks board. One way to do
this is through a wget command on the Gateworks board if the executable is hosted
on a web server.
4. Run the executable by chmod 777 if needed, and the type at the command line
./input
{{{
#include <stdio.h>
#include <string.h>
/*******************************
*
* get value of inputs on Gateworks Boards
*
**********************************/
int getValue(char *file)
{

FILE *fp;

int val=0;

fp = fopen(file,"r");
if ( fp == NULL)
{
printf("Bad open\n");
exit(0);
}

while(!feof(fp))
{
if(fscanf(fp,"%d", &val)!=1)
{
break;
}
else
{

printf("\nVal=%d\n\n",val);
}
}

fclose(fp);

return val;

}
/*******************************
*
* get name of inputs on Gateworks Boards
*
**********************************/
const char * getName(char *file)
{

FILE *fp;

char label[100];

fp = fopen(file,"r");
if ( fp == NULL)
{
printf("Bad open\n");
exit(0);
}

while(!feof(fp))
{
if(fscanf(fp,"%s", &label)!=1)
{
break;
}
else
{
printf("\n\nLabel=%s",label);
}
}

fclose(fp);
}

/*******************************
*
* dispatch name and value request Gateworks Boards
*
**********************************/
void getNameValuePair(char *file)
{
char filelabel[360];

strcpy(filelabel,file);
strcat (filelabel,"_label");
getName(filelabel);
strcat (file,"_input");
getValue(file);
}

/*****************************
*
* MAIN read inputs such as voltage
*
*****************************/
int main (int argc, char** argv)
{

int i=0;
char str[360];
char ival[2];
printf("About to read values...\n");

for(i=0;i<13;i++)
{
strcpy (str," ");
strcpy (str,"/sys/class/hwmon/hwmon0/device/in");
sprintf(ival,"%d",i);
strcat (str,ival);
getNameValuePair(str);

}
return 0;
}

}}}

The output once ran on the target Gateworks board looks like:
{{{
root@OpenWrt:/# ./input
About to read values...

Label=vin
Val=23852
Label=3p3
Val=3295

Label=bat
Val=3037

Label=5p0
Val=4983

Label=core
Val=1257

Label=cpu1
Val=16777215

Label=cpu2
Val=16777215

Label=dram
Val=1837

Label=ext_bat
Val=16777215

Label=io1
Val=2505

Label=io2
Val=16777215

Label=pci2
Val=1517

Label=current
Val=775

root@OpenWrt:/#
}}}

You might also like