路由器的硬件构成
路由器的软件构成
路由器固件开发的一般流程
Openwrt常用命令
1.文件、目录类命令:cd cat rm touch mkdir Is mv grep
2.文本编辑器命令:ⅵ
3.权限类命令:chmod
4.模块命令:rmmod insmod modprobe Ismod
5.进程管理命令:ps top kill killall
6.文件下载上传工具:scp wget tftp
7.系统命令:mount dmesg reboot chpasswd data time du df
8.网络类命令:ifconfig arp route iptables netstat
9.OpenWrt专用命令:sysupgrade opkg
Makefile入门教程-基本方法
目标(target):依赖1 依赖2 依赖3 。。。依赖n(prerequisites)
命令(command)
Makefile入门教程-特殊宏
Makefile四个动作 config、compile、install、clean
common.mak 是Makefile的缩写
all:libnvram.so libnvram.a nvram 定义了一个all 产生了libnvram.so、 libnvram.a 、nvram等三个文件 all在这里相当于隐含的compile
#
# This software is licensed under the Public Domain.
#
include $(TOPDIR)/rules.mk
PKG_NAME:=example1
PKG_VERSION:=0.1
PKG_RELEASE:=1
//这些是make menuconfig的配置 是必须的
PKG_MAINTAINER:=John Doe <john.doe@example.com>
PKG_LICENSE:=CC0-1.0
//这一部分可以直接放到src目录中去
include $(INCLUDE_DIR)/package.mk
include $(INCLUDE_DIR)/cmake.mk
define Package/example1
SECTION:=utils
# Select package by default
#DEFAULT:=y
CATEGORY:=Utilities
TITLE:=Some different dummy application.
URL:=https://www.example.com
endef
//这些是make menuconfig中能看到的信息
define Package/example1/description
This is some dummy application.
endef
//这些是make menuconfig中能看到的信息(description描述)
//define Build/Configure 编译配置
define Build/Prepare
mkdir -p $(PKG_BUILD_DIR)
$(CP) ./src/* $(PKG_BUILD_DIR)/
endef
//编译前
//define Build/Compile 编译
//有几个不是必须的,如果 不写 就是用默认的
define Package/example1/install
$(CP) ./files/* $(1)/
$(INSTALL_DIR) $(1)/usr/bin
$(INSTALL_BIN) $(PKG_BUILD_DIR)/example1 $(1)/usr/bin/
endef
//安装
$(eval $(call BuildPackage,example1))
如何创建package
拿了一个别人的demo - otrx文件
改第一层Makefile
在进行编译之前 可以先在修改的那个文件夹make一下查看是否报错
src文件夹中的各项文件也需要修改
openwrt如何逆向解析包-百度
openwrt如何创建开机自启动
开机启动一共涉及两个文件夹
/etc/init.d
/etc/rc.d
但实际上只会执行/etc/rc.d中的文件
openwrt中opkg应用实例
1 安装app时保留上一次的文件(升级时保留配置文件),通过preinst和 postinst 实现
1)在Makefile中加入preinst和 postinst //记得更新版本号
preinst 将 etc文件中的config 考入tmp目录中
postinst 将 tmp文件中的config 再考回到etc目录中 完成覆盖, 从而保证config文件的一致性
2)上传package
scp myapp_4_mipsel_24kc.ipk root@192.168.1.1:/tmp
3) opkg高版本文件
opkg intall myapp_4_mipsel_24kc.ipk
2 升级后保留配置文件
注意点:一定要用sysupgrade升级 而不能用uboot升级
1)创建config文件
2)在Makefile中加入 //相当于声明,则升级时会自动保留这个配置文件
define Package/myaoo/conffies
/etc/config/myapp
/etc/myapp.conf
endef
3)编译 make package/example/compile V=99
4) 让路由器和电脑虚拟机保持同一频段,然后上传package,上传至tmp目录
scp myapp_2_mipsel_24kc.ipk root@192.168.1.1:/tmp
5)在路由中修改配置,并用uci commit保存
查看机型:cat /proc/cpuinfo / ubus call system board
6)使用sysupgrade 进行升级,查看文件是否保留
上传bin文件 scp openwrt-ramips-mt7620-psg1218b-squashfs-sysupgrade.bin root@192.168.1.1:/tmp
升级:sysupgrade openwrt-ramips-mt7620-psg1218b-squashfs-sysupgrad //用串口能看到过程
openwrt Cron定时任务
1 每天晚上0点 重启路由
几分?几时?几日?几月?周几?
0 0 * * *
设置定时任务 //测试时要熟练掌握 date 命令
2 每天晚上11:00~早上8:00 关闭LED灯/无线
3 周一~周五 关闭WIFI
openwrt GPIO框架及其应用
GPIO:General-purpose input/output 输入/输出的接口
应用
1)LED灯 (USB WiFi)
软连接 使用GPIO控制 0 1 变化 会导致 CPU消耗
硬连接 引脚直接连接
2)复位键
3)WPS键
GPIO有几种访问方式
1)sysfs 文件形式
优点)不需要用c、可用Lua、Python
缺点)文件,所以速度慢,一般用于低速IO访问
2)ioctl 系统调用
优点)速度快
缺点)需要用c/c++
3)mmap 内存
用c语言、速度最快、跨平台
GPIO实验 output实验 蜂鸣器
电路连接图
1 进入路由控制台
2 进入 gpio目录 cd /sys/class/gpio
3 使能 42 号引脚 echo "42" > export
4 设置gpio口为推挽输出模式 echo "out" > direction
5 拉高电平:蜂鸣器响 echo "1" > value
mmap实验
实验之前打开 make menuconfig
打开
MediaTech(MTK) MT7628 MT7688 Linux 下使用mmap实现用户态 GPIO 驱动
/* forgotfun.org 佐须之男 */
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/mman.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define MMAP_PATH "/dev/mem"
#define RALINK_GPIO_DIR_IN 0
#define RALINK_GPIO_DIR_OUT 1
#define RALINK_REG_PIOINT 0x690
#define RALINK_REG_PIOEDGE 0x6A0
#define RALINK_REG_PIORENA 0x650
#define RALINK_REG_PIOFENA 0x660
#define RALINK_REG_PIODATA 0x620
#define RALINK_REG_PIODIR 0x600
#define RALINK_REG_PIOSET 0x630
#define RALINK_REG_PIORESET 0x640
#define RALINK_REG_PIO6332INT 0x694
#define RALINK_REG_PIO6332EDGE 0x6A4
#define RALINK_REG_PIO6332RENA 0x654
#define RALINK_REG_PIO6332FENA 0x664
#define RALINK_REG_PIO6332DATA 0x624
#define RALINK_REG_PIO6332DIR 0x604
#define RALINK_REG_PIO6332SET 0x634
#define RALINK_REG_PIO6332RESET 0x644
#define RALINK_REG_PIO9564INT 0x698
#define RALINK_REG_PIO9564EDGE 0x6A8
#define RALINK_REG_PIO9564RENA 0x658
#define RALINK_REG_PIO9564FENA 0x668
#define RALINK_REG_PIO9564DATA 0x628
#define RALINK_REG_PIO9564DIR 0x608
#define RALINK_REG_PIO9564SET 0x638
#define RALINK_REG_PIO9564RESET 0x648
static uint8_t* gpio_mmap_reg = NULL;
static int gpio_mmap_fd = 0;
static int gpio_mmap(void)
{
if ((gpio_mmap_fd = open(MMAP_PATH, O_RDWR)) < 0) {
fprintf(stderr, "unable to open mmap file");
return -1;
}
gpio_mmap_reg = (uint8_t*) mmap(NULL, 1024, PROT_READ | PROT_WRITE,
MAP_FILE | MAP_SHARED, gpio_mmap_fd, 0x10000000);
if (gpio_mmap_reg == MAP_FAILED) {
perror("foo");
fprintf(stderr, "failed to mmap");
gpio_mmap_reg = NULL;
close(gpio_mmap_fd);
return -1;
}
return 0;
}
int mt76x8_gpio_get_pin(int pin)
{
uint32_t tmp = 0;
/* MT7621, MT7628 */
if (pin <= 31) {
tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIODATA);
tmp = (tmp >> pin) & 1u;
} else if (pin <= 63) {
tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332DATA);
tmp = (tmp >> (pin-32)) & 1u;
} else if (pin <= 95) {
tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564DATA);
tmp = (tmp >> (pin-64)) & 1u;
tmp = (tmp >> (pin-24)) & 1u;
}
return tmp;
}
void mt76x8_gpio_set_pin_direction(int pin, int is_output)
{
uint32_t tmp;
/* MT7621, MT7628 */
if (pin <= 31) {
tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIODIR);
if (is_output)
tmp |= (1u << pin);
else
tmp &= ~(1u << pin);
*(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIODIR) = tmp;
} else if (pin <= 63) {
tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332DIR);
if (is_output)
tmp |= (1u << (pin-32));
else
tmp &= ~(1u << (pin-32));
*(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332DIR) = tmp;
} else if (pin <= 95) {
tmp = *(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564DIR);
if (is_output)
tmp |= (1u << (pin-64));
else
tmp &= ~(1u << (pin-64));
*(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564DIR) = tmp;
}
}
void mt76x8_gpio_set_pin_value(int pin, int value)
{
uint32_t tmp;
/* MT7621, MT7628 */
if (pin <= 31) {
tmp = (1u << pin);
if (value)
*(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIOSET) = tmp;
else
*(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIORESET) = tmp;
} else if (pin <= 63) {
tmp = (1u << (pin-32));
if (value)
*(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332SET) = tmp;
else
*(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO6332RESET) = tmp;
} else if (pin <= 95) {
tmp = (1u << (pin-64));
if (value)
*(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564SET) = tmp;
else
*(volatile uint32_t *)(gpio_mmap_reg + RALINK_REG_PIO9564RESET) = tmp;
}
}
int main(int argc, char **argv)
{
int ret = -1;
if (gpio_mmap())
return -1;
printf("get pin 39 input %d\n", mt76x8_gpio_get_pin(39));
printf("get pin 40 input %d\n", mt76x8_gpio_get_pin(40));
printf("get pin 41 input %d\n", mt76x8_gpio_get_pin(41));
printf("get pin 42 input %d\n", mt76x8_gpio_get_pin(42));
printf("set pin 39 output 1\n");
mt76x8_gpio_set_pin_direction(39, 1);
mt76x8_gpio_set_pin_value(39, 1);
printf("set pin 40 output 0\n");
mt76x8_gpio_set_pin_direction(40, 1);
mt76x8_gpio_set_pin_value(40, 0);
printf("set pin 41 output 1\n");
mt76x8_gpio_set_pin_direction(41, 1);
mt76x8_gpio_set_pin_value(41, 1);
printf("set pin 42 output 0\n");
mt76x8_gpio_set_pin_direction(42, 1);
mt76x8_gpio_set_pin_value(42, 0);
while (1)
{
mt76x8_gpio_set_pin_value(42, 0);
mt76x8_gpio_set_pin_value(42, 1);
}
close(gpio_mmap_fd);
return ret;
}
OpenWrt 基于GPIO、Hotplug、DTS 的按键实验
DTS是Device Tree Source的缩写,用来描述设备的硬件细节。在过去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备、resource、i2c_board_info、spi_board_info以及各种硬件的platform_data。为了去掉这些垃圾代码,Linux采用DTS这种新的数据结构来描述硬件设备。采用Device Tree后,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码。
.dtsi文件 都属于公共文件 ,能被其他文件依赖的
按键实验
选择GPIO1 偏移量6 则代表 GPIO口为32+6=38
GPIO_ACTIVE_LOW 代表低电平触发
KEY_WPS_BUTTON 定义了一个宏 代表了wps键
你现在要修改一个属于自己DTS ,先找到openwrt文件系统中的DTS源文件
OpenWrt vlan、switch、bridge、wans、lan、wlan、wifi等相关概念解析
OpenWrt基于DTS适配RAM、Flash、复位键、波特率、端口布局实验
openwrt软件移植
先从github上,下拉压缩包至本地,然后解压缩,config(下载以后会出现configure.in 我们需要autoconf,然后就会生成configure)、make。这样就可以查看软件所依赖的各类库(动态、静态)。
在自己的例子目录中新建wificat文件夹,并新建Makefile和src
回到下载的软件包 make distclean 清空编译的文件
然后复制粘贴到src文件夹下, make menuconfig选择文件夹,编译,上传,运行软件包
openwrt静态库和动态库
动态库:.so文件 运行时才加载,程序小,通常情况release下动态库
静态库:.a 直接编译到程序中,程序大,debug时使用静态库
xx.c->xx.o-LD-xx.so
-AR-xx.a