Chino 操作系统开发日志 (1) - 为 IoT 而生

引言

很多人都听说过 IoT (物联网)这个词,越来越多的人在装修时开始选择智能家居,很多人也购买智能音箱做智能家居控制,想必未来一定是 AI + 物联网的时代。

一种技术要发展并走向成熟必须要降低门槛,提高迭代速度。传统的嵌入式开发太碎片化,很多时候还在使用代码复制、粘贴、修改的开发方法。如果不提供一个开箱即用的开发平台,让砖瓦能一层层叠上去,是很难开发更高级的应用的。

因此需要一个这样的平台:

  • 提供足够的硬件抽象能力
  • 提供友好的编程接口和调试接口

同时结合 IoT 的特点还要:

 

  • 灵活控制非标准的定制硬件
  • 适应有限资源的运行设备

因此 IoT 操作系统应运而生。

目前很多公司已经开始布局 IoT 操作系统,如 RT-Thread,华为的 LiteOS 等。

Chino OS

Chino OS 由包括我在内的开发团队设计开发的一款开源 IoT 操作系统。GitHub 地址:https://github.com/chino-os/chino-os

Chino 主要使用 C++ 语言编写,配有专用的 GNU 工具链和 C 运行库,使用 DeviceTree 描述硬件配置。目前系统具有以下特性:

  • 多任务 (6 个优先级, Round robin 调度)
  • 线程同步 (Mutex, Recurisve Mutex, Semaphore, Event)
  • 进程间通信 (Mailslot)
  • 统一的驱动模型
  • 网络支持 (基于 LwIP 的 Socket API)

Chino 预定义了一组驱动接口,为应用开发者提供了一个统一的 API 层,使得开发者的大部分需求不用关心具体硬件差异。部分设备抽象如下表:

类别子类示例驱动
中断控制器 cortex-m3, nvic
IO / 总线GPIOstm32f10x, gpio
I²Cstm32f10x, i2c
SPIstm32f10x, spi
串行stm32f10x, uart
SDIOstm32f10x, sdio
存储EEPROMAT24C02
FlashGD25Q128
SD 内存卡SD V2.0 大容量存储
显示TFT LCDILI9486L
网络以太网ENC28J60
传感器加速度计ADXL345

Chino 目前支持 x86_64、Cortex-M3 架构,可运行在 PC 和 STM32 开发板上。未来计划支持 ESP32、RISCV32/64 等更多架构。

Chino 在 STM32F103 上的运行截图

Chino 在 STM32F103 开发板上的运行截图

代码示例

1. GPIO 亮小灯

亮小灯可以说是嵌入式开发的 Hello World 了。

 1 auto access = OA_Read | OA_Write;
 2 auto gpio = g_ObjectMgr->GetDirectory(WKD_Device).Open("gpio3", access).MoveAs<GpioController>();
 3 auto pin0 = gpio->OpenPin(0, access);
 4 pin0->SetDriveMode(GpioPinDriveMode::Output);
 5 
 6 while (true)
 7 {
 8     pin0->Write(GpioPinValue::Low);
 9     g_ProcessMgr->SleepCurrentThread(1s);
10     pin0->Write(GpioPinValue::High);
11     g_ProcessMgr->SleepCurrentThread(1s);
12 }

程序申请读写权限打开名为 “gpio3” 的 GPIO 控制器,然后打开第 0 个 Pin,并设置该 Pin 的驱动模式为输出。

然后间隔 1s 切换输出高低电平。

这段代码隐藏了硬件具体细节,在任意具有 GPIO 的硬件上无需修改代码便可运行。

2. 读写 Flash

 1 auto flash1 = g_ObjectMgr->GetDirectory(WKD_Device).Open("flash1", access).MoveAs<FlashStorage>();
 2 {
 3     gsl::span<const uint8_t> writeBuffers[] = { buffer };
 4     flash1->Write(0, { writeBuffers });
 5 }
 6 {
 7     gsl::span<uint8_t> readBuffers[] = { buffer };
 8     kassert(flash1->Read(0, { readBuffers }) == std::size(buffer));
 9     g_Logger->PutString("GD25Q128 Read:\n");
10     g_Logger->DumpHex(buffer, std::size(buffer));
11 }

这段代码功能很简单:打开 flash 之后写入数据然后读取数据。唯一需要说明的是 Chino 的 IO 部分均使用 BufferList 来读写数据,因此可以支持多个非连续内存段读写,且没有复制开销。

3. TCP Echo

 1 auto eth0 = g_NetworkMgr->InstallNetworkDevice(g_ObjectMgr->GetDirectory(WKD_Device).Open("eth0", OA_Read | OA_Write).MoveAs<EthernetController>());
 2 eth0->SetAsDefault();
 3 eth0->Setup();
 4 g_NetworkMgr->Run();
 5 
 6 auto bindAddr = std::make_shared<IPEndPoint>(IPAddress::IPv4Any, 80);
 7 auto socket = MakeObject<Socket>(AddressFamily::IPv4, SocketType::Stream, ProtocolType::Tcp);
 8 socket->Bind(bindAddr);
 9 socket->Listen(1);
10 
11 auto client = socket->Accept();
12 while (true)
13 {
14     const uint8_t text[] = "hello\n";
15     gsl::span<const uint8_t> buffers[] = { {text,6} };
16 
17     try
18     {
19         client->Send({ buffers });
20         g_ProcessMgr->SleepCurrentThread(1s);
21     }
22     catch (...)
23     {
24         break;
25     }
26 }

程序打开名为 “eth0” 的以太网控制器,并注册到网络子系统。

然后创建一个 Tcp Socket,并监听 80 端口。

接受一个客户端连接并循环输出 hello,直到连接被关闭则退出循环。

系列说明

本文作为 Chino 操作系统开发日志的第一篇,简单概述了 Chino 目前的开发进度和基本的编程模型。今后的文章会详细介绍各个子系统的设计和开发的最新进展。

欢迎大家提出批评和建议,帮助 Chino 发展得更好。

 

最后再次附上 Chino 项目地址:https://github.com/chino-os/chino-os,希望大家多 star,多提 issue。

转载于:https://www.cnblogs.com/sunnycase/p/chino-os-develop-blog-1-birth-for-iot.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值