AliOS Things 筆記
[TOC]
1技術架構總覽
1.1架構概述
從底部到頂部噪沙,AliOS Things包括:
- 板級支持包(BSP):主要由SoC供應商開發(fā)和維護
- 硬件抽象層(HAL):比如WiFi和UART
- 內(nèi)核:包括Rhino實時操作系統(tǒng)內(nèi)核、Yloop, VFS, KV 存儲
- 協(xié)議棧:包括TCP/IP協(xié)議棧(LwIP)泪喊,uMesh網(wǎng)絡協(xié)議棧
- 安全:安全傳輸層協(xié)議(TLS),可信服務框架(TFS)凭语、可信運行環(huán)境(TEE)
- AOS API:提供可供應用軟件和中間件使用的API
- 中間件:包括常見的物聯(lián)網(wǎng)組件和阿里巴巴增值服務中間件
- 示例應用:阿里自主開發(fā)的示例代碼极舔,以及通過了完備測試的應用程序(比如Alinkapp)
所有的模組都已經(jīng)被組織成組件镊屎,且每個組件都有自己的.mk文件,用于描述它和其它組件間的依賴關系,方便應用開發(fā)者按需選用气筋。
結構框圖
文件夾結構
文件夾名稱 | 內(nèi)容描述 |
---|---|
board | 評估板(如STM32L496G-Discovery) |
build | 編譯框架 |
device | 連接MCU/SoC的外設拆内,比如支持使用AT命令的WiFi系列模組 |
example | 代碼示例,通過了完備測試的應用程序(比如Alink) |
framework | IoT 通用組件 |
include | 系統(tǒng)頭文件 |
kernel | 包括Rhino和協(xié)議棧 |
platform | 芯片架構支持的相關文件 |
security | 包括TLS宠默,TFS麸恍, TEE在內(nèi)的安全組件 |
tools | 命令行界面(CLI)和用于建立遠程設備中心的testbed工具 |
utility | IoT通用軟件庫,比如 cJSON |
test | UT測試用例 |
2快速開始
2.1配置環(huán)境
在一臺 Ubuntu 14.04 LTS 64-bit PC 上
sudo apt-get install -y python
sudo apt-get install -y gcc-multilib
sudo apt-get install -y libssl-dev libssl-dev:i386
sudo apt-get install -y libncurses5-dev libncurses5-dev:i386
sudo apt-get install -y libreadline-dev libreadline-dev:i386
sudo apt-get install -y python-pip
sudo apt-get install -y minicom
2.2安裝 aos-cube
首先, 用 python 包管理器 pip 來安裝 aos-cube 和相關的依賴包在全局環(huán)境搀矫,以便于后續(xù)使用 AliOS Things Studio 進行開發(fā)抹沪。
$ pip install setuptools
$ pip install wheel
$ pip install aos-cube
請確認pip環(huán)境是基于 Python 2.7 的。如果遇到權限問題瓤球,可能需要 sudo 來執(zhí)行融欧。
如果在線安裝aos-cube失敗,可以下載源碼安裝卦羡,方法如下:
- 先下載你要安裝的包噪馏,并解壓(aos-cube-0.2.46.tar.gz)
$ cd aos-cube-0.2.46
$ python setup.py build
$ python setup.py install
2.3下載代碼并編譯運行
git clone https://github.com/alibaba/AliOS-Things.git
cd AliOS-Things
aos make helloworld@linuxhost
./out/helloworld@linuxhost/binary/helloworld@linuxhost.elf
2.4效果
可以看見 app_delayed_action 在1秒時啟動,每5秒觸發(fā)一次绿饵。
[ 0.000]<V> AOS [application_start#15] : application started.
[ 1.000]<V> AOS [app_delayed_action#9] : helloworld app_delayed_action:9 app_task
[ 6.000]<V> AOS [app_delayed_action#9] : helloworld app_delayed_action:9 app_task
[ 11.000]<V> AOS [app_delayed_action#9] : helloworld app_delayed_action:9 app_task
[ 16.000]<V> AOS [app_delayed_action#9] : helloworld app_delayed_action:9 app_task
[ 21.000]<V> AOS [app_delayed_action#9] : helloworld app_delayed_action:9 app_task
3 編譯過程
3.1 aos
2.2小結安裝了aos-cube欠肾,aos-cube封裝了一系列 AliOS Things使用的 Python包。
官方注解如下:
aos command line tool for repositories version control, publishing and updating code from remotely hosted repositories, and invoking aos own build system and export functions, among other operations
aos 用法如下:
[naiquanhu@naiquanhu-VirtualBox AliOS-Things]$ aos --help
usage: aos [-h] [--version] ...
Code management tool for aos - https://code.aliyun.com/aos/aos
version 0.2.46
Use 'aos <command> -h|--help' for detailed help.
Online manual and guide available at https://code.aliyun.com/aos/aos-cube
optional arguments:
-h, --help show this help message and exit
--version print version number and exit
Commands:
new Create new aos program or component
ls List cube info, default components info
import Import program from URL
add Add component from AOS_SDK_PATH or URL
rm Remove component
deploy Find and add missing components and source codes
codes Import the optional component from the remote repository
publish Publish program or component
update Update to branch, tag, revision or latest
sync Synchronize aos component references
status Show version control status
make Make aos program/component
scons Make aos program/component by scons
makelib Compile static library
config Tool configuration
upload Upload aos image
monitor Serial port monitor
devices List devices on serial ports
upgrade Upgrade aos-cube to latest
help This help screen
看一下aos程序內(nèi)容:
which aos
/usr/local/bin/aos
vi /usr/local/bin/aos
#!/usr/bin/python
# EASY-INSTALL-ENTRY-SCRIPT: 'aos-cube==0.2.46','console_scripts','aos'
__requires__ = 'aos-cube==0.2.46'
import sys
from pkg_resources import load_entry_point
if __name__ == '__main__':
sys.exit(
load_entry_point('aos-cube==0.2.46', 'console_scripts', 'aos')()
)
/usr/local/bin/aos會調用aos-cube-0.2.46/aos/aos.py
3.2 aos調用make過程
aos make helloworld@linuxhost
該命令會首先進入aos/aos.py中的main()
def _run_make(arg_list):
#install dependent toolchains
_install_toolchains(sys.argv[2:])
# check operating system
host_os = get_host_os()
if host_os == None:
error('Unsupported Operating System!')
#cd to aos root_dir
ret, original_dir = cd_aos_root()
if ret != 'success':
error("not in AliOS-Things source code directory")
make_cmds = {
'Win32': 'cmd/win32/make.exe',
'Linux64': 'cmd/linux64/make',
'Linux32': 'cmd/linux32/make',
'OSX': 'cmd/osx/make'
}
tools_dir = os.path.join(os.getcwd(), 'build').replace('\\', '/')
make_cmd = os.path.join(tools_dir, make_cmds[host_os])
# Run make command
make_cmd_str = ' '.join([make_cmd, 'HOST_OS=' + host_os, 'TOOLS_ROOT=' + tools_dir] + list(arg_list))
popen(make_cmd_str, shell=True, cwd=os.getcwd())
if os.path.isdir(original_dir): os.chdir(original_dir)
def make_build(make_args):
# aos new program
if os.path.isfile(os.path.join(os.getcwd(), Cfg.file)):
...
with cd(os_path):
...
_run_make(['-e', '-f build/Makefile', make_args, app_dir, build_dir])
else:
# aos source code
_run_make(['-e', '-f build/Makefile', make_args])
# Make command
@subcommand('make',
help='Make aos program/component',
description="Make aos program/component.")
def make():
...
args = sys.argv[2:]
...
make_args = ' '.join(args)
for arg in args:
if '@' in arg:
targets = arg.split('@')
...
board = targets[1]
if board in get_scons_enabled_boards():
scons_build(args)
else:
make_build(make_args)
return
#aos make clean go here
make_build(make_args)
def main():
...
# Parse/run command
if len(sys.argv) <= 1:
help_()
sys.exit(1)
...
pargs, remainder = parser.parse_known_args()
status = 1
try:
...
status = pargs.command(pargs)
except ProcessException as e:
...
sys.exit(status or 0)
if __name__ == "__main__":
main()
簡單來說拟赊,調用關系如下:
aos make helloworld@linuxhost
|-- make()
|-- make_build()
|-- _run_make(arg_list)
|-- popen(make_cmd_str, shell=True, cwd=os.getcwd())
變量的值:
build_dir = 'BUILD_DIR=./out/'
app_dir = 'APPDIR=./'
make_args = helloworld@linuxhost
arg_list = ['-e', '-f build/Makefile', make_args, app_dir, build_dir]
make_cmd = ./build/cmd/linux64/make
make_cmd_str = make_cmd + 'HOST_OS=Linux64' + 'TOOLS_ROOT=./build' + + list(arg_list)
其中董济,popen是Python的標準庫中的subprocess包的類,用來fork一個子進程并運行一個外部程序要门,進入 ./build/Makefile
3.3 make入口
build/Makefile是make的主入口,傳入的參數(shù)有:
HOST_OS=Linux64
TOOLS_ROOT=./build
BUILD_DIR=./out/
APPDIR=./
make_args = helloworld@linuxhost
我們先來看看build/Makefile中的一些關鍵內(nèi)容:
export SOURCE_ROOT ?= ./ #AliOS-Things 的根目錄
export MAKEFILES_PATH := $(SOURCE_ROOT)/build #MAKEFILES_PATH = ./build
export SCRIPTS_PATH := $(SOURCE_ROOT)/build/scripts #SCRIPTS_PATH = ./build/scripts
MAKEFILE_TARGETS := clean
#define BUILD_STRING, AOS toolchain commands on different hosts
include $(MAKEFILES_PATH)/aos_host_cmd.mk #./build/aos_host_cmd.mk
接著看一下文件./build/aos_host_cmd.mk:
TOOLS_ROOT ?= $(SOURCE_ROOT)build #TOOLS_ROOT = ./build
COMPILER_ROOT ?=$(TOOLS_ROOT)/compiler #COMPILER_ROOT = ./build/compiler
OPENOCD_PATH := $(TOOLS_ROOT)/OpenOCD/${HOST_OS}/ #OPENOCD_PATH = ./build/OpenOCD/Linux64/
OPENOCD_CFG_PATH := $(MAKEFILES_PATH)/OpenOCD/${HOST_OS}/ #OPENOCD_CFG_PATH = ./build/OpenOCD/Linux64/
JTAG ?= jlink_swd
BUILD_DIR ?= out
...
COMMON_TOOLS_PATH := $(TOOLS_ROOT)/cmd/linux64/
#COMMON_TOOLS_PATH = ./build/cmd/linux64/
export SHELL = $(COMMON_TOOLS_PATH)dash #SHELL = ./build/cmd/linux64/dash
OPENOCD_FULL_NAME := "$(OPENOCD_PATH)bin/openocd"
#OPENOCD_FULL_NAME = ./build/OpenOCD/Linux64/bin/openocd
ECHO := echo
PERL := $(shell which perl)
PYTHON := $(shell which python)
CLEAN_COMMAND := "$(COMMON_TOOLS_PATH)rm" -rf $(BUILD_DIR)
#CLEAN_COMMAND = "./build/cmd/linux64/rm" -rf out
MKDIR = "$(COMMON_TOOLS_PATH)mkdir" -p $1
#MKDIR = "./build/cmd/linux64/mkdir" -p $1
RMDIR = "$(COMMON_TOOLS_PATH)rm" -rf $1
#RMDIR = "./build/cmd/linux64/rm" -rf $1
CPDIR = "$(COMMON_TOOLS_PATH)cp" -rf $1 $2
#CPDIR = "./build/cmd/linux64/cp" -rf $1 $2
TRUE_CMD := true
FALSE_CMD := false
RM := "$(COMMON_TOOLS_PATH)rm$(EXECUTABLE_SUFFIX)" -f
#RM = "./build/cmd/linux64/rm" -f
CP := "$(COMMON_TOOLS_PATH)cp$(EXECUTABLE_SUFFIX)" -f
#CP = "./build/cmd/linux64/cp" -f
MAKE := "$(COMMON_TOOLS_PATH)make$(EXECUTABLE_SUFFIX)"
#MAKE = "./build/cmd/linux64/make"
BIN2C := "$(COMMON_TOOLS_PATH)bin2c$(EXECUTABLE_SUFFIX)"
#BIN2C = "./build/cmd/linux64/bin2c"
CURRENT_TIME = $(shell $(DATE) +%Y%m%d.%H%M)
SHOULD_I_WAIT_FOR_DOWNLOAD := $(filter download, $(MAKECMDGOALS))
#因為MAKECMDGOALS = helloworld@linuxhost廓啊,所以 SHOULD_I_WAIT_FOR_DOWNLOAD = null
BUILD_STRING ?= $(strip $(filter-out $(MAKEFILE_TARGETS) download run total, $(MAKECMDGOALS)))
#BUILD_STRING = "helloworld@linuxhost"
BUILD_STRING_TO_DIR = $(subst .,/,$(1))
#BUILD_STRING_TO_DIR = null
DIR_TO_BUILD_STRING = $(subst /,.,$(1))
#DIR_TO_BUILD_STRING = null
CLEANED_BUILD_STRING := $(BUILD_STRING)
#CLEANED_BUILD_STRING = "helloworld@linuxhost"
OUTPUT_DIR := $(BUILD_DIR)/$(CLEANED_BUILD_STRING)$(MBINS)
#OUTPUT_DIR = "out/helloworld@linuxhost"
AUTO_COMPONENT_DIR := $(OUTPUT_DIR)/auto_component
#AUTO_COMPONENT_DIR = "out/helloworld@linuxhost/auto_component"
主要設置了一些和host os相關的參數(shù)欢搜。
接著build/Makefile文件繼續(xù)看,由于IDE = null谴轮,則COMPILER = null
include $(MAKEFILES_PATH)/aos_toolchain_gcc.mk
AUTO_COMPONENT = $(AUTO_COMPONENT_DIR)/auto_component.mk
#AUTO_COMPONENT = "out/helloworld@linuxhost/auto_component/auto_component.mk"
TEST_COMPONENT_COLLECTION = $(AUTO_COMPONENT_DIR)/test_collection.default
#TEST_COMPONENT_COLLECTION = "out/helloworld@linuxhost/auto_component/test_collection.default"
$(AUTO_COMPONENT): $(TEST_COMPONENT_COLLECTION)
$(QUIET)$(PYTHON) $(MAKEFILES_PATH)/scripts/auto_component.py $(AUTO_COMPONENT_DIR)
$(TEST_COMPONENT_COLLECTION):
$(QUIET)$(PYTHON) $(MAKEFILES_PATH)/scripts/gen_test_collection.py $(AUTO_COMPONENT_DIR) $(TEST_COMPONENT_COLLECTION)
設置完一些變量的值后炒瘟,執(zhí)行2條python指令:
python ./build/scripts/gen_test_collection.py ./out/helloworld@linuxhost/auto_component ./out/helloworld@linuxhost/auto_component/test_collection.default
python ./build/scripts/auto_component.py ./out/helloworld@linuxhost/auto_component
命令:
aos make helloworld@linuxhost
該命令最先調用的targe是main_app:
main_app: $(OUTPUT_DIR)/config.mk $(YOS_SDK_PRE_APP_BUILDS) $(MAKEFILES_PATH)/aos_target_build.mk
$(if $(BINS_ERROR), $(call BINS_EXIT))
$(if $(MBINS_ERROR), $(call MBINS_EXIT))
$(QUIET)$(ECHO) Build AOS Now
$(QUIET)$(ECHO) TOOLCHAIN_PATH=$(TOOLCHAIN_PATH)
$(QUIET)$(call MKDIR, $(OUTPUT_DIR)/binary)
$(QUIET)$(call MKDIR, $(OUTPUT_DIR)/modules)
$(QUIET)$(call MKDIR, $(OUTPUT_DIR)/libraries)
$(QUIET)$(call MKDIR, $(OUTPUT_DIR)/resources)
$(QUIET)$(PYTHON) $(MAKEFILES_PATH)/scripts/gen_auto_code.py $(OUTPUT_DIR)/config.mk $(AUTO_COMPONENT_DIR)
$(QUIET)$(MAKE) -r $(JOBSNO) $(SILENT) -f $(MAKEFILES_PATH)/aos_target_build.mk $(CLEANED_BUILD_STRING) $(PASSDOWN_TARGETS)
$(QUIET)$(ECHO) Build complete
main_app又依賴$(OUTPUT_DIR)/config.mk,即out/helloworld@linuxhost/config.mk第步,所以先調用build/aos_target_config.mk生成out/helloworld@linuxhost/config.mk疮装,完成后,主要做了兩件事:
- /usr/bin/python .//build/scripts/gen_auto_code.py out/helloworld@linuxhost/config.mk out/helloworld@linuxhost/auto_component
根據(jù)out/helloworld@linuxhost/config.mk生成out/helloworld@linuxhost/auto_component下的文件粘都。 - ./build/cmd/linux64/make -r -j4 -f .//build/aos_target_build.mk helloworld@linuxhost
進入./build/aos_target_build.mk 繼續(xù)編譯廓推。
4 第一個應用Hello World
4.1 創(chuàng)建工程目錄及源文件
$ mkdir ./example/helloworld
$ cd ./example/helloworld
創(chuàng)建文件helloworld.c helloworld.mk
#helloworld.mk
NAME := helloworld ## 指定應用名稱
$(NAME)_SOURCES := helloworld.c ## 指定使用的源文件
#$(NAME)_DEFINES += LOCAL_MACRO ## 定義局部符號
GLOBAL_DEFINES += AOS_NO_WIFI ## 定義全局符號
$(NAME)_COMPONENTS := yloop cli ## 指定依賴的組件,本例使用yloop cli組件
ifeq ($(BENCHMARKS),1)
$(NAME)_COMPONENTS += benchmarks
GLOBAL_DEFINES += CONFIG_CMD_BENCHMARKS
endif
helloworld.c
static void app_delayed_action(void *arg)
{
LOG("helloworld %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[])
{
LOG("application started.");
aos_post_delayed_action(1000, app_delayed_action, NULL);
aos_loop_run();
return 0;
}
編譯運行參見2.3節(jié)翩隧。
5 Ubuntu下環(huán)境配置
5.1 下載安裝Jlink
SEGGER官網(wǎng)下載最新jlink驅動樊展,網(wǎng)址 https://www.segger.com/downloads/jlink
Select J-Link Software and Documentation Pack for Linux.
$ sudo dpkg -i JLink_Linux_V634_x86_64.deb
$ ls /opt/SEGGER/
JLink JLink_V634
設置環(huán)境JLink的環(huán)境變量:
vi ~/.bashrc
export JLINK_HOME=/opt/SEGGER/JLink
export PATH=${PATH}:${JLINK_HOME}
5.2 下載安裝GNU ARM Embedded Toolchain
download toolchain for Linux, URL: https://launchpad.net/gcc-arm-embedded/+download
解壓后放入目錄:/opt/gcc-arm-none-eabi-5_4-2016q3
設置環(huán)境Toolchain的環(huán)境變量:
vi ~/.bashrc
export ARM_TOOLCHAIN_HOME=/opt/gcc-arm-none-eabi-5_4-2016q3
export PATH=${PATH}:${ARM_TOOLCHAIN_HOME}/bin/:${JLINK_HOME}
5.3 連接開發(fā)板
$ JLinkExe
J-Link>connect
Device>CORTEX-M4
TIF>S
Speed>20
5.4 下載代碼
下載代碼到RAM中運行:
J-Link>loadbin firmware.bin 0x1fff0000
J-Link>setpc 0x1fff01fd
J-Link>g
可以整理為腳本:
xxx.jlink
loadbin firmware.bin 0x1fff0000
setpc 0x1fff01fd
g
#q #退出jlink
在控制臺窗口中輸入 JLink xxx.jlink 即可。