AliOS-Things 文档

AliOS Things 是阿里巴巴旗下物联网操作系统。阿里巴巴发布物联网操作系统 AliOS Things 主要目的是让阿里巴巴的物联网技术普惠更多的开发者和用户,助力实现更加美好的物联网时代。

目录

AliOS-Things 简介

AliOS-Things 是 AliOS 家族旗下面向 IoT 领域的轻量级物联网嵌入式操作系统, 将致力于搭建云端一体化 IoT 基础设施,具备极致性能、极简开发、云端一体、丰富组件、安全防护等关键能力,并支持终端设备连接到阿里云 Link,可广泛应用在智能家居、智慧城市、新出行等领域。

AliOS Things 特性

  • 极简开发
    • 基于 Linux 平台,提供 MCU 虚拟化环境,开发者直接在 Linux 平台上开发硬件无关的 IoT 应用和软件库,使用 GDB/Valgrind/SystemTap 等 PC 平台工具诊断开发问题
    • 提供 IDE,支持系统/内核行为 Trace、Mesh 组网图形化显示
    • 提供 Shell 交互,支持内存踩踏、泄露、最大栈深度等各类侦测
    • 提供面向组件的编译系统以及 Cube 工具,支持灵活组合 IoT 产品软件栈
    • 提供包括存储(掉电保护、负载均衡)在内的各类产品级别的组件
  • 即插即用的连接和丰富服务
    • 支持 umesh 即插即用网络技术,设备上电自动连网
    • 通过 Alink 与阿里云计算 IoT 服务无缝连接
  • 细颗粒度的 FOTA 更新
    • 支持应用代码独立编译映像,IoT App 独立极小映像升级
    • 支持映像高度压缩
  • 彻底全面的安全保护
    • 提供系统和芯片级别安全保护
    • 支持可信运行环境(支持 ARMV8-M Trust Zone)
    • 支持预置 ID2 根身份证和非对称密钥以及基于 ID2 的可信连接和服务
  • 高度优化的性能
    • 内核支持 Idle Task 成本,Ram < 1K,Rom < 2k,提供硬实时能力
    • 提供 YLOOP 事件框架以及基于此整合的核心组件,避免栈空间消耗,核心架构良好支持极小 FootPrint 的设备
  • 解决 IoT 实际问题的特性演进
    • 更好的云端一体融合优化,更简单的开发体验,更安全,更优整体性能和算法支持,更多的特性演进,我们在路上
    • Stay Hungry,Stay Foolish!

搭建开发环境

硬件环境准备

以庆科 MK3060 模组为例,介绍 AliOS Things 硬件环境的搭建,其他模组的硬件环境可参考本节。

mk3060模组

MK3060 是基于 ARM 核的 Wi-Fi 模组:

https://img.alicdn.com/tfs/TB1dkGJdwoQMeJjy0FoXXcShVXa-4160-2336.jpg
串口线

MK3060 的串口已经通过miniusb接口接出,通过 miniusb-usb 线将串口与 PC 连接起来:

https://img.alicdn.com/tfs/TB16paGdwoQMeJjy0FnXXb8gFXa-4160-2336.jpg
调试器

支持 Jlink 调试器:

https://img.alicdn.com/tfs/TB1bXEjg3MPMeJjy1XcXXXpppXa-4160-2336.jpg
连接示例

连接好的硬件环境:

https://img.alicdn.com/tfs/TB1ThvGg3MPMeJjy1XdXXasrXXa-4160-2336.jpg

windows环境配置

aos-cube安装

aos-cube 是 AliOS Things 在 Python 下面开发的项目管理工具包,依赖 Python 2.7 版本(在Python 2.7.14 版本上验证测试通过)。在 Python 官网下载对应的 2.7 版本的 Python MSI 安装文件,安装时,选择 pipadd python.exe to Path 两个选项:

https://img.alicdn.com/tfs/TB1SlHyjqmgSKJjSspiXXXyJFXa-798-688.png

安装配置完成 Python 后,使用 pip 安装 aos-cube:

> pip install aos-cube
交叉工具链

Windows 工具链可以在链接 GCC 下载 Windows的exe安装,勾选 Add path to environment variable 选项:

https://img.alicdn.com/tfs/TB16JofcWagSKJjy0FaXXb0dpXa-865-620.png

在 AliOS Things 源码的目录下面,运行:

$ aos make helloworld@mk3060

编译 mk3060 板子的 helloworld 示例程序。

驱动安装
串口驱动

FTDI系列

FTDI驱动,在 FTDI 下载 Windows 驱动程序并安装。

对应驱动安装完成后,连接设备,可在计算机 - 设备管理 - 端口,查看对应转换端口状态:

https://img.alicdn.com/tfs/TB1Fflnd3MPMeJjy1XcXXXpppXa-864-633.png

驱动安装完成后,连接串口线,配置串口参数。在 MobaXterm Personal Edition 下,以MK3060为例,Session - Serial,选择端口,波特率为921600, Advanced Serial setting 里面,Software 选择 Minicom (allow manual COM port setting):

https://img.alicdn.com/tfs/TB1Fg4ibjihSKJjy0FiXXcuiFXa-865-522.png

对应参数配置好一会,点击 OK 按钮,查看串口日志。

jtag驱动

J-Link

J-Link 驱动可在 SEGGER J-Link驱动下载地址 下,选择 J-Link Software and Documentation Pack,选择 J-Link Software and Documentation pack for Windows 下载安装:

https://img.alicdn.com/tfs/TB1s4L9bLNNTKJjSspfXXbXIFXa-865-466.png

安装完成 J-Link 驱动后,需要安装 J-Link 的 libusb 驱动 zadig,下载后解压缩,运行 zadig.exe 或 zadig_xp.exe(Window XP系统):

https://img.alicdn.com/tfs/TB1xyN2fgMPMeJjy1XcXXXpppXa-865-432.png

选择 J-Link,driver 选择libusb-win32(v1.2.6.0),点击 Replace Driver,返回 successful 说明 libusb 安装成功:

https://img.alicdn.com/tfs/TB1OHStfgMPMeJjy1XcXXXpppXa-865-512.png

关闭 zadig.exe,可在计算机 - 设备管理,查看 J-Link 识别状态:

https://img.alicdn.com/tfs/TB1XZcYaWagSKJjy0FhXXcrbFXa-865-568.png

连接 J-Link 烧写或者调试。

如果此时无法法连接上 J-Link,或者烧写调试失败,在选择 J-Link 的 libusb 驱动选择时,尝试选择 libusbK (v3.0.7.0) (由于不同厂家的使用的 J-Link 固件版本不同,libusb-win32(v1.2.6.0)可能无法正常驱动J-Link)。

linux环境配置

依赖及aos-cube安装

以 Ubuntu 16.04 LTS (Xenial Xerus) 64-bit PC 版本为例,安装下列 pkg:

$ sudo apt-get install -y python \
      gcc-multilib \
      libssl-dev libssl-dev:i386 \
      libncurses5-dev libncurses5-dev:i386 \
      libreadline-dev libreadline-dev:i386 \
      python-pip minicom
$ sudo pip install aos-cube
交叉工具链

Linux 工具链可以在链接 GCC 下载 Linux 压缩包,解压缩,在 .bashrc 里面配置 TOOLCHAIN_PATH 路径(注意:路径最后一个下划线 / 添加到路径):

https://img.alicdn.com/tfs/TB1GnAGg3oQMeJjy0FpXXcTxpXa-865-413.png

在 AliOS Things 源码的目录下面,运行:

$ aos make helloworld@mk3060

编译 mk3060 板子的 helloworld 示例程序。

minicom串口配置

配置串口参数(以MK3060为例),配置文件(/etc/minicom/minirc.dfl)内容 :

pu port             /dev/ttyUSB0
pu baudrate         921600
pu bits             8
pu parity           N
pu stopbits         1
pu rtscts           No

启动 minicom,查看串口日志。

应用程序开发指导

概述

本文将描述如何基于AliOS Things源码进行应用开发,涉及的内容包括:软硬件环境搭建、如何创建第一个应用程序、AliOS Things重要开发组件的使用等。

软硬件环境准备

AliOS Things支持多种硬件平台。开发应用的硬件环境包括开发板、串口、调试器、烧录器等。 AliOS Things支持命令行工具和IDE两种开发方式。AliOS Things 开发环境的搭建请参照 搭建 AliOS Things 开发环境

应用开发步骤

基于AliOS Things可以很方便地进行应用开发。命令行工具主要适用于使用Linux的开发者。IDE环境则适合在Windows下使用。

命令行工具进行应用开发

命令行工具下的应用的开发步骤主要包括工程目录的创建、工程Makefile编写、源码编写、工程编译、程序烧录、调试等步骤。

创建工程目录

AliOS Things的应用工程一般放在“example”目录下,用户也可以根据需要在其他目录下创建应用工程的目录。

添加 Makefile

Makefile 用于指定应用的名称、使用到的源文件、依赖的组件、全局符号等。下面是 helloworld.mk 样例文件的内容:

NAME := helloworld  ## 指定应用名称
$(NAME)_SOURCES := helloworld.c  ## 指定使用的源文件
$(NAME)_COMPONENTS += cli  ## 指定依赖的组件,本例使用cli组件
$(NAME)_DEFINES += LOCAL_MACRO ## 定义局部符号
GLOBAL_DEFINES += GLOBAL_MACRO ## 定义全局符号
添加源码

所有的源码文件放置在应用工程目录下,开发者可以根据自行组织源码文件/目录。AliOS Things的应用程序入口为:

int application_start(int argc, char *argv[]);
编译、烧录和调试
在AliOS Studio中进行应用开发

AliOS Things提供了AliOS Things Studio集成开发环境,基于AliOS Things Studio进行应用开发非常方便、快捷。AliOS Things Studio提供了可供导入的应用模版,用户可以基于导入的模版进行应用开发。AliOS Things Sutdio也支持编译、烧录、调试等。

创建应用项目

关于如何在AliOS Things Studio中创建应用,请参考`使用AliOS Things Studio创建应用 <https://github.com/alibaba/AliOS-Things/wiki/AliOS-Things-Studio#22-创建-app-项目>`_。创建完项目后,用户可以在AliOS Things Studio中添加、编辑应用代码。

编译、烧录和调试

AliOS Things Studio下的编译、烧录和调试步骤,可以参照:IDE开发环境

第一个 AliOS Things 应用

本节以helloworld工程为例来说明如何创建一个AliOS Things应用(基于命令行工具)。

创建工程目录

在“example”目录下添加helloworld工程目录。

创建Makefile

在hellworld工程目录下,创建helloworld.mk文件,并添加Makefile内容:

NAME := helloworld
$(NAME)_SOURCES := helloworld.c
创建源文件

在hellworld工程目录下,创建helloworld.c文件,并添加以下源代码:

#include <aos/aos.h>

static void app_delayed_action(void *arg)
{
    printf("%s:%d %s\r\n", __func__, __LINE__, aos_task_name());
    aos_post_delayed_action(5000, app_delayed_action, NULL);
}

int application_start(int argc, char *argv[])
{
    aos_post_delayed_action(1000, app_delayed_action, NULL);
    aos_loop_run();
    return 0;
}
Linux 模拟环境下运行

AliOS Things支持linuxhost的模拟环境,可以快速进行功能的验证:

$ aos make helloworld@linuxhost
$ ./out/helloworld@linuxhost/binary/helloworld@linuxhost.elf
app_delayed_action:24 app

当然,你可以使用gdb,valgrind等工具调试上述应用。

上板编译、烧录和运行

应用的编译、烧录和调试可以参考:Linux开发环境。helloworld应用启动后串口打印如下:

https://img.alicdn.com/tfs/TB11fSrdwMPMeJjy1XdXXasrXXa-231-161.png

开发组件介绍

AliOS Things提供了丰富的组件来支持IoT应用的开发。

yloop

yloop是一个异步事件框架,主要负责管理系统各类事件的分发处理,及各类微任务(action)的调度。基于yloop,开发者可以避免多线程编程引入的复杂度和资源占用。yloop支持监听本地事件和网络事件,支持延时调用,支持workqueue处理耗时事件。AliOS Things系统起来后有一个main yloop,也支持任务创建属于自己的yloop。yloop提供了注册,发送事件的接口。开发者可以用这些接口编写基于事件监听机制的程序,以及和系统其他组件的消息通信。yloop接口介绍

Kernel

kernel是AliOS Things的核心组件之一,其基础是代号为Rhino的实时操作系统。AliOS Things kernel实现了多任务机制,多个任务之间的调度,任务之间的同步、通讯、互斥、事件,内存分配,trace功能,多核等等的机制。开发者可以利用kernel提供的api来实现一个RTOS所具备的能力。开发者可以利用现有已移植的CPU体系架构来达到快速的移植能力。Kernel接口介绍

硬件抽象层(HAL)

HAL是AliOS Things的核心组件之一,主要目的是为了屏蔽底下不同的芯片平台的差异,从而使上面的应用软件不会因为不同的芯片而改变。目前ALiOS Things定义了丰富的HAL抽象层,芯片公司或者用户只要对接相应的HAL接口即能满足控制芯片的控制器,从而达到控制硬件外设的目的。HAL包含的功能有adc,flash, gpio,i2c,pwm,rng,rtc,sd,spi,timer,uart,wdg。开发者可以利用HAL的API来快速达到控制硬件外设的能力。由于目前的HAL层是非常标准的API,开发者可以参考现有移植的HAL层的开发,来达到快速移植的能力。HAL接口介绍

KV

KV组件是基于键(key)-值(value)数据类型的小型轻量级持久化存储组件,主要为基于Nor-Flash的小型嵌入式设备提供通用的key-value持久化存储接口。KV组件支持写平衡(磨损平衡)与掉电保护;而且,KV组件的资源占用较低,RAM占用峰值固定,只和最大键值对长度相关。KV组件封装了简洁的增加/修改、删除及查询的接口方法,开发者可以通过这些接口方法存储一些产品参数、系统配置等信息。KV组件的移植请参照:KV移植KV接口介绍

VFS

VFS是AliOS Things核心组件之一,用户可以使用VFS组件通过统一的接口操作不同的真实文件系统和设备。VFS组件是对真实文件系统操作与设备操作的一层抽象层,VFS组件封装了一套对文件对象与设备对象执行操作的统一接口,具有良好的跨平台性。开发者可以通过VFS组件封装的统一接口(aos_open、aos_read,etc.)来操作真实文件系统与设备。而且利用VFS组件的统一接口来进行应用开发,可以让应用具有更好的跨平台性,不再依赖设备HAL层接口定义和各个真实文件系统的接口定义。VFS接口介绍

uMesh

uMesh是AliOS Things核心组件之一,模组之间通过uMesh能够形成自组织网络。uMesh实现了mesh链路管理、mesh路由、6LoWPAN、AES-128数据加解密等。它能够支持mesh原始数据包、IPv4或IPv6多种数据传输方式。开发者可以使用熟悉的socket编程,利用uMesh提供的自组织网络实现智能设备的开发和互连,能够使用在智能照明,智能抄表,智能家居等场景。开发者也可以通过实现uMesh提供的mesh HAL层接口,将uMesh移植到不同的通信介质,如WiFi,802.15.4, BLE等。

CLI

AliOS Things应用开发中可以支持命令行,并且可以添加用户自定义命令。当需要注册或撤销自定义命令时,可以借助“CLI”组件。CLI接口介绍

下图展示了一个实际示例应用中的命令列表。

https://img.alicdn.com/tfs/TB1ETiGdwMPMeJjy1XcXXXpppXa-447-367.png

总结

本文描述了基于AliOS Things的应用模型,介绍了软硬件开发环境的搭建、应用开发的基本步骤。以helloworld为例,展示了如何基于AliOS Things进行应用开发。本文最后,还介绍了AliOS Things提供的丰富组件和接口,以及如何利用这个组件进行应用开发。 想了解AliOS Things更详细的信息,请访问`AliOS Things Github主页 <https://github.com/alibaba/AliOS-Things>`_。

集成开发环境 AliOS Studio

移植指导

API 指导

Kernel API

int aos_task_setspecific(aos_task_key_t key, void * vp)

Associate a task-specific value with a key.

Return
the check status, 0 is OK, -1 indicates invalid.
Parameters
  • key: key object.
  • vp: pointer of a task-specific value.

void* aos_task_getspecific(aos_task_key_t key)

Get the value currently bound to the specified key.

Parameters
  • key: key object.

int aos_mutex_new(aos_mutex_t * mutex)

Alloc a mutex.

Return
0: success.
Parameters
  • mutex: pointer of mutex object, mutex object must be alloced, hdl pointer in aos_mutex_t will refer a kernel obj internally.

void aos_mutex_free(aos_mutex_t * mutex)

Free a mutex.

Parameters
  • mutex: mutex object, mem refered by hdl pointer in aos_mutex_t will be freed internally.

int aos_mutex_lock(aos_mutex_t * mutex, unsigned int timeout)

Lock a mutex.

Return
0: success.
Parameters
  • mutex: mutex object, it contains kernel obj pointer which aos_mutex_new alloced.
  • timeout: waiting until timeout in milliseconds.

int aos_mutex_unlock(aos_mutex_t * mutex)

Unlock a mutex.

Return
0: success.
Parameters
  • mutex: mutex object, it contains kernel obj pointer which oc_mutex_new alloced.

int aos_mutex_is_valid(aos_mutex_t * mutex)

This function will check if mutex is valid.

Return
0: success.
Parameters
  • mutex: pointer to the mutex.

int aos_sem_new(aos_sem_t * sem, int count)

Alloc a semaphore.

Return
0:success.
Parameters
  • sem: pointer of semaphore object, semaphore object must be alloced, hdl pointer in aos_sem_t will refer a kernel obj internally.
  • count: initial semaphore counter.

void aos_sem_free(aos_sem_t * sem)

Destroy a semaphore.

Parameters
  • sem: pointer of semaphore object, mem refered by hdl pointer in aos_sem_t will be freed internally.

int aos_sem_wait(aos_sem_t * sem, unsigned int timeout)

Acquire a semaphore.

Return
0: success.
Parameters
  • sem: semaphore object, it contains kernel obj pointer which aos_sem_new alloced.
  • timeout: waiting until timeout in milliseconds.

void aos_sem_signal(aos_sem_t * sem)

Release a semaphore.

Parameters
  • sem: semaphore object, it contains kernel obj pointer which aos_sem_new alloced.

int aos_sem_is_valid(aos_sem_t * sem)

This function will check if semaphore is valid.

Return
0: success.
Parameters
  • sem: pointer to the semaphore.

void aos_sem_signal_all(aos_sem_t * sem)

Release all semaphore.

Parameters
  • sem: semaphore object, it contains kernel obj pointer which aos_sem_new alloced.

int aos_queue_new(aos_queue_t * queue, void * buf, unsigned int size, int max_msg)

This function will create a queue.

Return
0: success.
Parameters
  • queue: pointer to the queue(the space is provided by user).
  • buf: buf of the queue(provided by user).
  • size: the bytes of the buf.
  • max_msg: the max size of the msg.

void aos_queue_free(aos_queue_t * queue)

This function will delete a queue.

Parameters
  • queue: pointer to the queue.

int aos_queue_send(aos_queue_t * queue, void * msg, unsigned int size)

This function will send a msg to the front of a queue.

Return
0: success.
Parameters
  • queue: pointer to the queue.
  • msg: msg to send.
  • size: size of the msg.

int aos_queue_recv(aos_queue_t * queue, unsigned int ms, void * msg, unsigned int * size)

This function will receive msg from a queue.

Return
0: success.
Parameters
  • queue: pointer to the queue.
  • ms: ms to wait before receive.
  • msg: buf to save msg.
  • size: size of the msg.

int aos_queue_is_valid(aos_queue_t * queue)

This function will check if queue is valid.

Return
0: success.
Parameters
  • queue: pointer to the queue.

void* aos_queue_buf_ptr(aos_queue_t * queue)

This function will return buf ptr if queue is inited.

Return
NULL: error.
Parameters
  • queue: pointer to the queue.

int aos_sched_disable(void)

This function will disable kernel sched.

Return
the operation status, 0 is OK, others is error.

int aos_sched_enable(void)

This function will enable kernel sched.

Return
0: success.

int aos_timer_new(aos_timer_t * timer, void(*fn)(void *, void *), void * arg, int ms, int repeat)

This function will create a timer.

Return
0: success.
Parameters
  • timer: pointer to the timer.
  • fn: callbak of the timer.
  • arg: the argument of the callback.
  • ms: ms of the normal timer triger.
  • repeat: repeat or not when the timer is created.

void aos_timer_free(aos_timer_t * timer)

This function will delete a timer.

Parameters
  • timer: pointer to a timer.

int aos_timer_start(aos_timer_t * timer)

This function will start a timer.

Return
0: success.
Parameters
  • timer: pointer to the timer.

int aos_timer_stop(aos_timer_t * timer)

This function will stop a timer.

Return
0: success.
Parameters
  • timer: pointer to the timer.

int aos_timer_change(aos_timer_t * timer, int ms)

This function will change attributes of a timer.

Return
0: success.
Parameters
  • timer: pointer to the timer.
  • ms: ms of the timer triger.

int aos_workqueue_create(aos_workqueue_t * workqueue, int pri, int stack_size)

This function will creat a workqueue.

Return
0: success.
Parameters
  • workqueue: the workqueue to be created.
  • pri: the priority of the worker.
  • stack_size: the size of the worker-stack.

void aos_workqueue_del(aos_workqueue_t * workqueue)

This function will delete a workqueue.

Parameters
  • workqueue: the workqueue to be deleted.

int aos_work_init(aos_work_t * work, void(*fn)(void *), void * arg, int dly)

This function will initialize a work.

Return
0: success.
Parameters
  • work: the work to be initialized.
  • fn: the call back function to run.
  • arg: the paraments of the function.
  • dly: ms to delay before run.

void aos_work_destroy(aos_work_t * work)

This function will destroy a work.

Parameters
  • work: the work to be destroied.

int aos_work_run(aos_workqueue_t * workqueue, aos_work_t * work)

This function will run a work on a workqueue.

Return
0: success.
Parameters
  • workqueue: the workqueue to run work.
  • work: the work to run.

int aos_work_sched(aos_work_t * work)

This function will run a work on the default workqueue.

Return
0: success.
Parameters
  • work: the work to run.

int aos_work_cancel(aos_work_t * work)

This function will cancel a work on the default workqueue.

Return
0: success.
Parameters
  • work: the work to cancel.

void* aos_realloc(void * mem, unsigned int size)

Realloc memory.

Return
NULL: error.
Parameters
  • mem: current memory address point.
  • size: new size of the mem to remalloc.

void* aos_malloc(unsigned int size)

Alloc memory.

Return
NULL: error.
Parameters
  • size: size of the mem to malloc.

void* aos_zalloc(unsigned int size)

Alloc memory and clear to zero.

Return
NULL: error.
Parameters
  • size: size of the mem to malloc.

void aos_alloc_trace(void * addr, size_t allocator)

Trace alloced mems.

Parameters
  • addr: pointer of the mem alloced by malloc.
  • allocator: buildin_address.

void aos_free(void * mem)

Free memory.

Parameters
  • ptr: address point of the mem.

long long aos_now(void)

Get current time in nano seconds.

Return
elapsed time in nano seconds from system starting.

long long aos_now_ms(void)

Get current time in mini seconds.

Return
elapsed time in mini seconds from system starting.

void aos_msleep(int ms)

Msleep.

Parameters
  • ms: sleep time in milliseconds.

CLI API

static int aos_cli_register_command(const struct cli_command * command)
static int aos_cli_unregister_command(const struct cli_command * command)
static int aos_cli_register_commands(const struct cli_command * commands, int num_commands)
static int aos_cli_unregister_commands(const struct cli_command * commands, int num_commands)

Warning

doxygenfunction: Cannot find function “aos_cli_printf” in doxygen xml output for project “AliOS-Things” from directory: xml

static int aos_cli_init(void)
static int aos_cli_stop(void)

Cloud API

int aos_cloud_register_callback(int cb_type, aos_cloud_cb_t cb)

Register cloud event callback.

Return
the operation status, 0 is OK, others is error.
Parameters
  • cb_type: event type interested.
  • cb: cloud event callback.

int aos_cloud_report(const char * method, const char * json_buffer, void(*done_cb)(void *), void * arg)

Report event to cloud.

Return
the operation status, 0 is OK, others is error.
Parameters
  • method: remote method name.
  • json_buffer: method’s payload.
  • done_cb: report done callback.
  • arg: private data passed to done_cb.

void aos_cloud_trigger(int cb_type, const char * json_buffer)

Trigger specific event, used by Cloud Backend.

Parameters
  • cb_type: event type.
  • json_buffer: payload.

void aos_cloud_register_backend(int(*report)(const char *method, const char *json_buffer))

Register Cloud Backend.

Parameters
  • report: called when user do aos_cloud_report.

KV API

Log API

Version API

const char* aos_get_product_model(void)

Get aos product model.

Return
model success, 0 failure.

const char* aos_get_os_version(void)

Get aos os version.

Return
os version success, 0 failure.

const char* aos_get_kernel_version(void)

Get aos kernel version.

Return
kernel version success, 0 failure.

const char* aos_get_app_version(void)

Get aos app version.

Return
app version success, 0 failure.

const char* aos_get_device_name(void)

Get aos device name.

Return
device name success, 0 failure.

void dump_sys_info(void)

dump sys info.

编码风格

规范原则

  • 朴实,避免晦涩语法
  • 严谨,逻辑反复思考
  • 简约,命名简洁、代码精炼
  • 性能,通过算法、编译器、硬件进行优化

目录结构

  • 原则

    整个工程按照功能模块划分子目录,每个子目录再划分头文件和源文件目录,以便架构清晰、易懂。

  • 示例

    在比较复杂的项目时,建议目录结构如下:

    https://img.alicdn.com/tfs/TB1G7lQdwMPMeJjy1XcXXXpppXa-432-281.png

    在项目相对简单时,建议目录结构如下:

    https://img.alicdn.com/tfs/TB1r5dIdwoQMeJjy1XaXXcSsFXa-461-217.png

系统组件

目录设计
  • 原则

    目录的命名能准确描述模块的基本功能,建议用小写字母且不含下划线、点等特殊符号;

    目录必须放于相包含的父目录之下,并需要明确与其他目录间的耦合性。

  • 示例

    • kernel:系统内核部分;
    • libs:依赖库;
    • mqtt:mqtt协议库;
    • external/mbedtls:位于第三方库目录的mbedtls库
依赖关系
  • 原则

    新添加组件往往依赖于系统原有组件,必须以最小耦合的方式明确所直接依赖的组件。

  • 示例

头文件

文件命名
  • 原则

    头文件命名能准确描述文件所包含的模块内容,达到通俗、易懂的目的。

  • 示例

版权声明(阿里集团内部)
  • 原则

    项目内的所有头文件(除引入的第三方库)版权声明一致,并且在文件内顶格注释。

  • 示例

    如AliOS版权声明如下:

    /*
     * Copyright (C) 2015-2017 Alibaba Group Holding Limited
     */
    
引用保护
  • 原则

    项目内的所有头文件采用#define宏防止多重包含,命名格式为:

    XXX_FILENAME_H

    Note

    为了保证宏定义的惟一性,建议“XXX”命名为头文件目录名、路径名或有意义的其他符号(如“k”: kernel)。

  • 示例

    如下图,在版权声明后空一行,且在“#endif”后空一行且添加注释(注释内容两边各留一个空格且采用“/* */”格式)。

    /*
     * Copyright (C) 2015-2017 Alibaba Group Holding Limited
     */
    
    #ifndef K_ERR_H
    #define K_ERR_H
    
    #endif /* K_ERR_H */
    
引用方式
  • 原则

    系统头文件和第三方库通过“<.h>”方式引用,其他文件通过“.h”引用。

  • 示例

函数定义
  • 原则

    由于C++编译器在编译时与C编译器命名不同,为了保证C++代码能够正确调用C接口, 建议在C语言接口声明时采用extern的方式指示编译器按C语言去编译。

  • 示例

    如下图,在extern的声明代码上下各添加一行空行。

    /*
     * Copyright (C) 2015-2017 Alibaba Group Holding Limited
     */
    
    #ifndef K_ERR_H
    #define K_ERR_H
    
    #ifdef __cplusplus
    extern "C" {
    #endif
    
    
    #ifdef __cplusplus
    }
    #endif
    
    #endif /* K_ERR_H */
    

源文件

文件命名
  • 原则

    源文件命名能准确描述文件所包含的模块内容,达到通俗、易懂的目的。

  • 示例

版权声明
  • 原则

    项目内的所有头文件(除引入的第三方库)版权声明一致,并且在文件内顶格注释。

  • 示例

    如AliOS版权声明如下:

    /*
     * Copyright (C) 2015-2017 Alibaba Group Holding Limited
     */
    
头文件依赖
  • 原则

    在源文件中引入头文件时采用如下顺序:C库、C++库、其他第三方库、项目内头文件, 同一类型的头文件采用字母顺序排列,避免引入冗余头文件。

  • 示例

函数定义
  • 原则

    源文件中函数的定义顺序严格按照头文件中声明的顺序排列,且内部函数添加static关键字,比较短的函数还需添加inline关键字。 对外函数必须进行参数检查,内部函数不做检查参数要求。返回值必须类型匹配。

  • 示例

命名风格

原则
  • 统一,相同含义的单词、命名方式项目内统一。
  • 准确,采用计算机领域常用单词。
  • 风格,采用字符加下划线的方式(不使用驼峰风格)
缩写
类型命名
  • 原则

    数据结构类型以“_t”结尾,枚举变量类型以“_e”结尾,回调函数类型以“_cb”结尾;或所有类型以“_t”作为后缀。字符均小写。

  • 示例

    typedef int (*xxx0_cb)(...);
    
    typedef struct {
        ...
    } xxx1_t;
    
    typedef struct xxx2_s {
        struct xxx2_s *x;
        ...
    } xxx2_t;
    
    typedef enum {
        ...
    } xxx3_e;
    
变量命名
  • 原则

    全局变量以“g_”作为前缀,内部变量尽量简洁,每个变量的字段不超过5个,字符均小写。

  • 示例

常量命名
  • 原则

    常量命名各字段必须大写,且字段数不超过5个。

  • 示例

函数命名
  • 原则

    对外的函数建议采用统一前缀,如“aos_”,源文件内部函数建议以“_”作为前缀,且命名字段数不超过5个,字符均小写。

  • 示例

枚举命名
  • 原则

    枚举命名各字段必须大写,且字段数`不超过5个`。

  • 示例

宏命名
  • 原则

    宏命名各字段必须大写,且字段数`不超过5个`。

  • 示例

注释方式

注释风格
  • 原则

    统一采用“/**/”方式注释,且注释内容左右各留一个空格,如“/* message */”;注释必须使用英文。

  • 示例

函数注释
  • 原则

    对外接口按doxgen要求的格式书写,且注释和函数定义间不留空行; 对内接口在需要时添加注释,注释位于定义前。

  • 示例

变量注释
  • 原则

    注释在变量定义后,在仅有一个需要注释的变量时与分号之间只留一个空格; 若多行变量定义均需注释,则最长变量定义留一个空格,其他注释与其对齐。

  • 示例

编译宏注释
  • 原则

    注释在宏定义后,在仅有一个需要注释的宏时与分号之间只留一个空格; 若多行宏定义均需注释,则最长宏定义后留一个空格,其他注释与其对齐。

  • 示例

所有的缩进必须使用空格(除makefile外不允许使用tab),且以`四个空格`为单位进行缩进。 嵌套的编译条件判断顶格写,且需要在“#endif”后的注释中备注属于哪个判断条件。
  • 示例

    #ifdef XXX
    int func1(void)
    {
        ...
    #ifdef XX
        func();
    #endif /* XX */
        ...
    }
    #endif /* XXX */
    
空行
  • 原则

    在所有需要空行的地方仅空一行,如版权声明与代码之间,不同类型的头文件引用之间,函数定义之间等。

  • 示例

变量声明
  • 原则

    全局变量的声明必须放在相关头文件中,且单个声明的类型和变量之间留一个空格,多个声明时按最长的留一个空格对齐。

  • 示例

    extern int   g_x_x;       /* ... */
    extern int   g_xx_xx;     /* ... */
    extern long  g_xxx_xxx;   /* ... */
    extern char *g_xxxx_xxxx; /* ... */
    
变量定义
  • 原则

    全局变量的定义必须放在相关的源文件中,且在头文件和函数定义之间; 局部变量的定义必须放在函数作用域的最开始处; 变量定义的类型和变量之间(或者“*”)留一个空格,当有多个变量时按照最长原则对齐。

  • 示例

    Note

    上图中描述了四种情况下的对齐方式

结构体声明
  • 原则

    在头文件中引用其他项目内头文件的结构体定义时采用extern进行声明,不引入相关头文件。

  • 示例

结构体定义
  • 原则

    结构体定义放在相关头文件中,并且在函数声明前,结构体定义前后需要各空一行。

  • 示例

函数声明
  • 原则

    对外函数的声明必须放在头文件中,且在头文件中按照关联性排序; 当每行超过`80列`时需将参数移到下一行且与上一行参数首字符对齐; 函数内紧邻左右大括号的参数不需要空格,但参数之间需要留一个空格; 仅一个函数时,返回类型与函数定义之间空一格,当多个关联函数时,返回最长的类型与函数定义之间空一格,其他关联函数首字符与其对齐。 对内声明的参数除放在源文件中外,其他与对外声明的函数保持一致。

  • 示例

    命名顺序、空格、空行、参数换行请参考下图。

    int xxx_xxx_func1(void);
    int xxx_xxx_func2(void);
    
    int   xxx_xxx_func3(...);
    int   xxx_xxx_func4(...);
    void  xxx_xxx_func5(...);
    void *xxx_xxx_func6(...);
    
函数定义
  • 原则

    函数的定义原则上在源文件中实现,且其定义的顺序与声明保持一致; 在函数定义时,需要将大括号另起一行,且代码逻辑紧邻大括号后一行; 函数之前留一空行。

  • 示例

    int xxx_func1(void)
    {
        return 0;
    }
    
    int xxx_func2(void)
    {
        return 0
    }
    
    int xxx_func3(void)
    {
        return 0;
    }
    
函数调用
  • 原则

    函数调用风格与定义基本相同,在超过`80列`时按照相同的规范处理; 需要对函数调用的返回值进行判断,且判断语句与上一条语句之间不留空行。

  • 示例

    int xxx_func(void)
    {
        int ret;
    
        ret = xxx_func1(...);
        if (ret != 0) {
            ...
            return ret;
        }
    
        return 0;
    }
    
条件语句
  • 原则

    条件判断必须明确,如“if (var)”形式应该写为“if (var != 0)”; 指针是否为空时必须与NULL进行对比(不建议用0),整型返回值可通过与1/0进行对比。

  • 示例

    if (var != 0) {
        return -1;
    }
    
    if (ret != 0) {
        ...
        return -2;
    }
    
循环语句
  • 原则

    风格与条件判断语句类似。

  • 示例

    for (i = 0; i < 100; i++) {
        ...
    }
    
    while (ret == 1) {
        ...
    }
    
    do {
        ...
    } while(ret != 1);
    

源码

AliOS-Things 是一款开源的操作系统,采用开源协议许可 Apache 2.0 license,其源代码托管于 GitHub 仓库 alibaba/AliOS-Things

快速入门

现在让我们开始构建第一个 Hello World Example 应用,体验 AliOS Things 的极致开发体验。