OpenLinux 平台详解
OpenLinux 架构
移远 OpenLinux 基于 Yocto Project 构建,是专为 IoT 模组优化的嵌入式 Linux 发行版。
OpenLinux 软件栈:
┌─────────────────────────────────────────┐
│ 用户应用程序 │
│ C/C++ / Python / Shell / Node.js │
├─────────────────────────────────────────┤
│ 系统库 │
│ glibc / OpenSSL / libcurl / libmosquitto│
├─────────────────────────────────────────┤
│ 系统服务 │
│ systemd / NetworkManager / udev │
├─────────────────────────────────────────┤
│ Linux 内核(4.x / 5.x) │
│ 驱动:USB / UART / SPI / I2C / GPIO │
├─────────────────────────────────────────┤
│ Bootloader(U-Boot) │
└─────────────────────────────────────────┘文件系统结构
/
├── bin/ # 基本命令(ls, cp, mv 等)
├── dev/ # 设备文件
│ ├── ttyUSB0 # USB 串口
│ ├── ttyHS0 # 硬件串口
│ ├── i2c-0 # I2C 总线
│ └── spidev0.0 # SPI 设备
├── etc/ # 配置文件
│ ├── systemd/ # systemd 服务配置
│ └── network/ # 网络配置
├── lib/ # 系统库
├── opt/ # 用户应用程序(推荐安装位置)
├── proc/ # 进程信息(虚拟文件系统)
├── sys/ # 系统信息(虚拟文件系统)
├── tmp/ # 临时文件
└── usr/ # 用户程序和库网络配置
蜂窝网络连接
bash
# 方法1:使用 quectel-CM(推荐)
# quectel-CM 是移远提供的连接管理工具
./quectel-CM -s cmnet & # 后台运行,-s 指定 APN
# 查看网络接口
ip addr show
# 会出现 wwan0 或 usb0 接口
# 查看路由
ip route show
# 测试连通性
ping -c 3 8.8.8.8
# 方法2:使用 ModemManager
mmcli -m 0 --simple-connect="apn=cmnet"
# 方法3:AT 指令手动配置
# 通过 /dev/ttyUSB2(AT 指令端口)
echo -e "AT+CGDCONT=1,\"IP\",\"cmnet\"\r\n" > /dev/ttyUSB2
echo -e "AT+CGACT=1,1\r\n" > /dev/ttyUSB2开机自动连接
bash
# 创建 systemd 服务
cat > /etc/systemd/system/quectel-cm.service << 'EOF'
[Unit]
Description=Quectel Connection Manager
After=network.target
[Service]
Type=simple
ExecStart=/usr/bin/quectel-CM -s cmnet
Restart=always
RestartSec=10
[Install]
WantedBy=multi-user.target
EOF
systemctl enable quectel-cm.service
systemctl start quectel-cm.serviceGPIO 操作
sysfs 接口(传统方式)
bash
# 导出 GPIO
echo 10 > /sys/class/gpio/export
# 设置方向
echo out > /sys/class/gpio/gpio10/direction
# 设置值
echo 1 > /sys/class/gpio/gpio10/value # 高电平
echo 0 > /sys/class/gpio/gpio10/value # 低电平
# 读取输入
echo in > /sys/class/gpio/gpio11/direction
cat /sys/class/gpio/gpio11/valuelibgpiod(现代方式)
c
#include <gpiod.h>
#include <stdio.h>
int main() {
struct gpiod_chip *chip;
struct gpiod_line *line;
// 打开 GPIO 芯片
chip = gpiod_chip_open("/dev/gpiochip0");
if (!chip) {
perror("Open chip failed");
return -1;
}
// 获取 GPIO 线
line = gpiod_chip_get_line(chip, 10); // GPIO 10
// 请求输出
gpiod_line_request_output(line, "myapp", 0);
// 设置高电平
gpiod_line_set_value(line, 1);
// 释放资源
gpiod_line_release(line);
gpiod_chip_close(chip);
return 0;
}I2C 操作
c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#define I2C_BUS "/dev/i2c-0"
#define SHT30_ADDR 0x44
int main() {
int fd = open(I2C_BUS, O_RDWR);
if (fd < 0) {
perror("Open I2C failed");
return -1;
}
// 设置从设备地址
ioctl(fd, I2C_SLAVE, SHT30_ADDR);
// 发送测量命令(单次测量,高精度)
unsigned char cmd[2] = {0x2C, 0x06};
write(fd, cmd, 2);
usleep(500000); // 等待 500ms
// 读取 6 字节数据
unsigned char data[6];
read(fd, data, 6);
// 解析温度和湿度
unsigned int raw_temp = (data[0] << 8) | data[1];
unsigned int raw_hum = (data[3] << 8) | data[4];
float temperature = -45.0 + 175.0 * raw_temp / 65535.0;
float humidity = 100.0 * raw_hum / 65535.0;
printf("Temperature: %.1f°C, Humidity: %.1f%%\n", temperature, humidity);
close(fd);
return 0;
}SPI 操作
c
#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#define SPI_DEVICE "/dev/spidev0.0"
int main() {
int fd = open(SPI_DEVICE, O_RDWR);
// 配置 SPI 参数
uint8_t mode = SPI_MODE_0;
uint8_t bits = 8;
uint32_t speed = 1000000; // 1MHz
ioctl(fd, SPI_IOC_WR_MODE, &mode);
ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits);
ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
// 全双工传输
uint8_t tx_buf[4] = {0x01, 0x02, 0x03, 0x04};
uint8_t rx_buf[4] = {0};
struct spi_ioc_transfer transfer = {
.tx_buf = (unsigned long)tx_buf,
.rx_buf = (unsigned long)rx_buf,
.len = 4,
.speed_hz = speed,
.bits_per_word = bits,
};
ioctl(fd, SPI_IOC_MESSAGE(1), &transfer);
printf("Received: %02X %02X %02X %02X\n",
rx_buf[0], rx_buf[1], rx_buf[2], rx_buf[3]);
close(fd);
return 0;
}