【openwrt应用开发】openwrt交叉编译自己的应用程序入门
类似minicom串口终端at应用程序开发
准备
开发板: sun7628 (mt7628 rom:32mb ram:128mb)
openwrt源码: openwrt chaos calmer(cc) 15.05.1 r49396
前提:编译openwrt源码包通过
openwrt应用程序开发方式
openwrt上面应用程序开发有两种方式:
1、利用openwrt sdk,
2、利用openwrt源码。
其实过程都差不是很多。源码会直接生成可执行程序的demo,sdk只生成ipk包,进行opkg安装。
在编译根目录下会有一个dl的目录,这个目录其实是“download”的简写,在编译前期,需要从网络下载的数据包都会放在这个目录下,这些软件包的一个特点就是,会自动安装在所编译的固件中,也就是我们make menuconfig的时候,为固件配置的一些软件包。如果我们需要更改这些源码包,只需要将更改好的源码包打包成相同的名字放在这个目录下,然后开始编译即可。编译时,会将软件包解压到build_dir目录下。
openwrt应用程序开发
很多入门教程都写hellowrold, 写helloword没什么实际用途,本次制作一个类似minicom串口终端, 我命名为at, minicom太大,我们自己写的at非常小,使用简单方便,相信大家用后会爱不释手。
下面我们利用openwrt源码开发at:
1、进入package目录,创建软件目录
#cd openwrt/package
#mkdir at
2、进入test目录,创建makefile文件和代码路径
├── at
├── makefile
└── src
├── at.c
└── makefile
该makefile基本内容格式都差不多,可参照以下进行修改
#
# copyright (c) 2009-2010 jo-philipp wich
#
# this is free software, licensed under the gnu general public license v2.
# see /license for more information.
#
# 导入通用编译规则
include $(topdir)/rules.mk
# name和version用来定义编译目录名$(pkg_build_dir)]
pkg_name:=at
pkg_version:=1.0
pkg_release:=1
#pkg_build_dir:=$(build_dir)/$(pkg_name) # 也可以直接定义编译目录名,代替默认的目录名
# 导入包定义
include $(include_dir)/package.mk
# 包定义:定义我们的包在menuconfig中的位置
# makefile中的define语法可以理解为函数,用于定义命令集合
define package/at
section:=utils
category:=base system
title:=at, uart at from example.
endef
# 包描述:关于我们包的更详细的描述
define package/at/description
a simple at example for uart utils, my first openwrt package example.
endef
# 编译准备. 必须使用tab缩进,表示是可执行的命令
define build/prepare
echo here is build/prepare at
mkdir -p $(pkg_build_dir)
cp ./src/* $(pkg_build_dir)/
endef
# 安装
define package/at/install
$(install_dir) $(1)/usr/bin
$(install_bin) $(pkg_build_dir)/at $(1)/usr/bin
endef
# 这一行总是在最后
$(eval $(call buildpackage,at))
复制代码
注意以上凡是命令行,必须以tab开头,否则会出现makefile *** missing separator. stop.
#mkdir src
3、进入src目录,创建相关源文件
#cd src
创建源文件at.c,如下
/*
* at
* like minicom
* usage: ./at /dev/ttyx
* lojam
* http://bbs.sunsili.com
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int ttyfd;
int stdout_changed = 0;
int tty_changed = 0;
struct termios stdout_tio;
struct termios tty_tio;
void restore_tio()
{
if(stdout_changed)
{
stdout_tio.c_lflag |= echo;
tcsetattr(stdin_fileno, tcsanow, &stdout_tio);
}
if(tty_changed)
{
tcsetattr(ttyfd, tcsanow, &tty_tio);
}
}
void int_handler(int signum)
{
close(ttyfd);
exit(exit_success);
}
int main(int args, const char *argv[])
{
char readbuf[256];
const char *ttypath = argv[1];
const char *atcommand = argv[2];
struct termios tio;
int ret;
if(args !=2 )
{
fprintf(stderr, usage: ./at /dev/ttyx );
exit(exit_failure);
}
atexit(restore_tio);
ttyfd = open(ttypath, o_rdwr | o_noctty | o_ndelay);
if(ttyfd < 0)
{
perror(open);
exit(exit_failure);
}
signal(sigint, int_handler);
ret = tcgetattr(ttyfd, &tio);
if (ret == -1)
{
perror(tcgetattr);
exit(exit_failure);
}
memcpy(&tty_tio, &tio, sizeof(struct termios));
tio.c_iflag = 0;
tio.c_oflag = 0;
tio.c_cflag = cs8 | cread | clocal;
tio.c_cflag &= (~crtscts);
tio.c_lflag = 0;
tio.c_cc[vmin] = 1;
tio.c_cc[vtime] = 0;
if (cfsetospeed(&tio, b115200) < 0 || cfsetispeed(&tio, b115200) < 0)
{
perror(cfseti/ospeed);
exit(exit_failure);
}
ret = tcsetattr(ttyfd, tcsanow, &tio);
if (ret == -1)
{
perror(tcsetattr);
exit(exit_failure);
}
tty_changed = 1;
struct termios outio;
ret = tcgetattr(stdin_fileno, &outio);
if (ret == -1)
{
perror(tcgetattr);
exit(exit_failure);
}
memcpy(&stdout_tio, &outio, sizeof(struct termios));
stdout_changed = 1;
outio.c_lflag &= ~echo;
ret = tcsetattr(stdin_fileno, tcsanow, &outio);
int flags = fcntl(stdin_fileno, f_getfl, 0);
fcntl(stdin_fileno, f_setfl, flags | o_nonblock);
struct pollfd fds[] = {
{stdin_fileno, pollin, 0},
{ttyfd, pollin, 0}
};
while (1)
{
ret = poll(fds, sizeof(fds)/sizeof(struct pollfd), 0);
if (ret == -1)
{
perror(poll);
exit(exit_failure);
}
if (fds[0].revents & pollin)
{
memset(readbuf, 0, sizeof(readbuf));
ret = read(fds[0].fd, readbuf, sizeof(readbuf));
if (ret 0)
{
strcpy(readbuf+ret-1, );
// printf(%s, readbuf);
ret = write(ttyfd, readbuf, strlen(readbuf));
if (ret < 0)
{
perror(write);
exit(exit_failure);
}
}
}
if (fds[1].revents & pollin)
{
memset(readbuf, 0, sizeof(readbuf));
ret = read(fds[1].fd, readbuf, sizeof(readbuf));
if (ret == -1 && errno != eagain)
{
perror(read);
exit(exit_failure);
}
printf(%s, readbuf);
}
}
int commandlen = strlen(atcommand);
char *buf = (char *)malloc(commandlen + 3);
sprintf(buf, %s , atcommand);
ret = write(ttyfd, buf, strlen(buf));
if (ret
at
选中行按空格键我们刚刚创建的at。保存退出
单独编译at模块
make package/at/compile v=s
make[1]: entering directory '/home/fan/openwrt_cc_mt76xx_omj_source'
make[2]: entering directory '/home/fan/openwrt_cc_mt76xx_omj_source/package/libs/toolchain'
if [ -f /home/fan/openwrt_cc_mt76xx_omj_source/staging_dir/target-mipsel_24kec+dsp_uclibc-0.9.33.2/pkginfo/toolchain.default.install.clean ]; then rm -f /home/fan/openwrt_cc_mt76xx_omj_source/staging_dir/target-mipsel_24kec+dsp_uclibc-0.9.33.2/pkginfo/toolchain.default.install /home/fan/openwrt_cc_mt76xx_omj_source/staging_dir/target-mipsel_24kec+dsp_uclibc-0.9.33.2/pkginfo/toolchain.default.install.clean; fi; echo libc >> /home/fan/openwrt_cc_mt76xx_omj_source/staging_dir/target-mipsel_24kec+dsp_uclibc-0.9.33.2/pkginfo/toolchain.default.install
.........
make[2]: leaving directory '/home/fan/openwrt_cc_mt76xx_omj_source/package/at'
make[1]: leaving directory '/home/fan/openwrt_cc_mt76xx_omj_source'
不出意外,就编译好了
也可以编译openwrt固件时编译,编译固件,参考:【openwrt】基于 wsl的openwrt开发环境(构建系统)配置-谷动谷力 (sunsili.com)
观察编译过程可以发现交叉编译工具为cc=mips-openwrt-linux-uclibc-gcc 位置大概是./staging_dir/toolchain-mips_34kc_gcc-4.8-linaro_uclibc-0.9.33.2/mips-openwrt-linux-uclibc/bin/
编译成功后,
#ls build_dir/target-mipsel_24kec+dsp_uclibc-0.9.33.2/at-1.0/at at.c at.o ipkg-ramips_24kec makefile
编译openwrt打包进固件
直接make (-j8 需要电脑支持)
编译成功后
生成ipk安装好
.......
generating index for package ./at_1.0-1_ramips_24kec.ipk
......
at应用程序存放位置
ls staging_dir/target-mipsel_24kec+dsp_uclibc-0.9.33.2/root-ramips/usr/bin/
可以找到 at
at_1.0-1_ramips_24kec.ipk ipk包存放位置
ls bin/ramips/packages/base/
可以找到 at_1.0-1_ramips_24kec.ipk
测试
单独编译的at模块
用scp拷贝at到开发板,执行就ok了。
scp build_dir/target-mipsel_24kec+dsp_uclibc-0.9.33.2/at-1.0/at root@19
2.168.3.125:/root
root@192.168.3.125's password: #输入openwrt开发板密码
at 100% 12kb 12.2kb/s 00:00
等待传输完成
ssh登录开发板(可以用可视化工具,如mobaxterm,点击可以查看用法)
ssh root@192.168.3.125
root@192.168.3.125's password:#输入openwrt开发板密码
busybox v1.23.2 (2023-07-31 0921 cst) built-in shell (ash)
_______ ________ __
| |.-----.-----.-----.| | | |.----.| |_
| - || _ | -__| || | | || _|| _|
|_______|| __|_____|__|__||________||__| |____|
|__| w i r e l e s s f r e e d o m
-----------------------------------------------------
chaos calmer (chaos calmer, r49396)
-----------------------------------------------------
* 1 1/2 oz gin shake with a glassful
* 1/4 oz triple sec of broken ice and pour
* 3/4 oz lime juice unstrained into a goblet.
* 1 1/2 oz orange juice
* 1 tsp. grenadine syrup
-----------------------------------------------------
root@sun:~# ls -la
.....
-rwxr-xr-x 1 root root 12487 aug 1 14:06 at #绿色的, 可执行的, root有执行权限
....
在开发板运行at测试一下, 我开发板开有一个air724模块,用ttyusb0端
usage: ./at /dev/ttyusb0
运行加端口号即可
root@tj:~# ./at /dev/ttyusb0
ati #发行at指令
airm2m_air724ug_v401876_lte_at #air724模块 返回air724模块软硬件相关信息
ok
同时ctrl+c 可以退出 at 应用
openwrt打包编译
用scp拷贝at_1.0-1_ramips_24kec.ipk到开发板
scp ./bin/ramips/packages/base/at_1.0-1_ramips_24kec.ipk root@192.168.3
.125:/tmp
root@192.168.3.125's password:
at_1.0-1_ramips_24kec.ipk 100% 3108 3.0kb/s 00:00
等待传输完成
安装at
在开发板上运行
root@sun:~# opkg install /tmp/at_1.0-1_ramips_24kec.ipk
installing at (1.0-1) to root...
configuring at.
运行at (安装后,无论在何目录下,都不用加./ 加路径,可以直接用at /dev/ttyx 运行
root@sun:~# at /dev/ttyusb0
ati
airm2m_air724ug_v401876_lte_at
ok
烧录固件
用scp拷贝penwr升级固件k到开发板
scp bin/ramips/openwrt-ramips-mt7628-mt7628-squashfs-sysupgrade.bin root@192.168.3.125:/tmp
root@192.168.3.125's password:
openwrt-ramips-mt7628-mt7628-squashfs-sysupgrade.bin 100% 8704kb 1.1mb/s 00:08
开发板运行:
sysupgrade -n -f /tmp/openwrt-ramips-mt7628-mt7628-squashfs-sysupgrade.bin
详细说明openwrtl固件升级,请参考:openwrt怎么升级固件?使用命令sysupgrade实现openwrt升级固件-谷动谷力 (sunsili.com)
烧录后,at会存放在开发析的 /usr/bin目录下,不用安装,无论在何目录下,都不用加./ 加路径,可以直接用at /dev/ttyx 运行
运行at
root@sun:~# at /dev/ttyusb0
ati
airm2m_air724ug_v401876_lte_at
ok
物联网应用场景正逐渐落地,vivo将全力布局IoT市场
DRAM和NAND预计将占汽车内存收入的近90%
太阳辐射变送器在太阳能领域的应用
光合作用测定仪是什么,它的作用又是什么
比克电池:高容量硅负极技术是探索三元锂电池性能突破的关键所在
OpenWrt应用程序开发之minicom串口终端
瞄准大数据通信 泰克力推新系列高速码型发生器
spacex猎鹰9火箭成功发射 60颗Starlink卫星送上预定轨道
华为对印度市场重视程度不足,多种原因导致华为在印度市场再受挫
为什么选择矩阵式KVM切换器,它的原理分析
全球DRAM平均价格上扬,但2019年DRAM市况应会出现供过于求情况
什么是电碳表 电碳表的功能
智慧城市的兴起 将促进小间距LED显示屏的发展
RS推出莫仕2300种新产品,呈现最大互联解决方案
上汽通用五菱宣布已在宝骏基地厂区建成一条无人驾驶物流线路 实现无人自主运输
高通SW3100处理器将为手表市场带来什么样的改变
四款极具性价比的手机推荐:魅族Pro6 plus,荣耀9,小米6和一加5
中国微电子为何屡次更名转型
涅槃汽车: 智能座舱数据存储技术浅析
这样的iPhone8设计,又会让无数人折腰