OpenWrt SDK
OpenWrt SDK
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.
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>
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).
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
}}}
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
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)
}}}
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)
= Additional Resources =
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:/#
}}}