Revision | Date | Description |
---|---|---|
1.0 | 2021-11-09 | 文档初版 |
EVB_AIoT是腾讯物联网操作系统TencentOS tiny 团队联合恩智浦半导体、厚德物联网设计的一款高性能AIoT评估板,用于TencentOS tiny 基础内核和AIoT应用功能体验和评估。 开发板如下图所示:
内置TencentOS Tiny开源物联网操作系统
NXP RT1062跨界处理器,最高主频528M
1M RAM 16M SDRAM 64MB qspi flash 128MB spi flash
板载Type-C接口CMSIS DAP仿真器
板载PCIE接口,可扩展4G类物联网模组
板载物联网俱乐部WAN Interface接口,可支持NB-IoT、WiFi、4G cat1、LoRa等模组
板载物联网俱乐部E53 Interface接口,可扩展全系E53传感器;
板载标准24P DVP摄像头接口,可支持最高500万像素摄像头;
板载RGB显示接口,可转换HDMI输出;
板载高性能音频解码芯片,可做语音识别测试;
预留SD卡、用户按键、SPI Flash
MCUXpresso IDE,是恩智浦公司为开发人员提供的一款基于Eclipse的集成开发环境,可以支持基于ARM Cortex M内核的NXP MCU。MCUXpresso IDE 提供高级编辑、编译和调试功能,并添加了特定于 MCU 的调试视图、代码跟踪和分析、多核调试和集成配置工具,可以帮助开发者基于NXP官方SDK快速搭建MCU软件开发环境。
登录NXP官网,下载MCUXpresso IDE软件,下载地址: https://www.nxp.com/design/software/development-software/mcuxpresso-software-and-tools-/mcuxpresso-integrated-development-environment-ide:MCUXpresso-IDE?tab=Design_Tools_Tab
这里我下载的版本当前最新的MCUXpresso IDE v11.4.1,本开发教程以该版本为例,双击下载下来的安装文件,按照提示完成安装即可。 安装完成启动软件可以看到如下欢迎界面:
然后我们就可以使用IDE了,如图,可以下载安装不同MCU 芯片的官方SDK,可以创建新的项目,可以导入官方SDK的应用案例等。
安装完 MCUXpresso IDE后,我们需要安装开发套件中MCU型号对应的SDK包。 在欢迎界面点击 DownLoad and Install SDKs按钮,或者在项目界面点击按钮,如下图,进入SDK选择界面
进入SDK选择界面后,输入对应的MCU RT1060,开始筛选SDK包,选择对应MCU系列的官方EVK,再点击Install即可完成安装,如下图:
至此,我们开发板的开发环境已经搭建完毕,可以开始进行代码开发。
工具下载: http://www.daxia.com/download/sscom.rar
安装方法:串口调试助手sscom5.13.1是免安装的,解压出压缩包即可直接使用。
根据PC和终端之间的连接,选择正确的串行端口。 打开电脑的设备管理器,在端口列表可以看到PC与开发板连接的端口号。
我这里显示的是COM6,所以要在sscom工具中选择COM6,开发板程序波特率设置为115200,所以我在sscom串口工具中选择115200波特率。
关闭欢迎界面,我们在左下方Create or import a project 选型卡里面选择Import SDK examples ,开始从SDK里面导入Hello World 示例。如下图所示。
进入向导后选择SDK,然后下一步
在demo apps 里面选择hello world示例,点击完成,即可生成hello World项目
生成项目后,可以在工程上右键选择构建项目来完成代码编译,如下图:
完成编译后,正确连接 usb typec 到 5V IN 端口,同时注意 SW1 应该拨到 AT MCU 一侧,如下图:
接着在工程上右键选择调试方式,再选择CMSIS-DAP(开发板板载了CMSIS DAP调试器)进行工程下载和调试,如下图:
如果出现下载失败,可能是mcu跑飞了,这时候需要配置下boot引脚,boot配置表如下:
boot0 | boot1 | |
---|---|---|
默认模式:Flash启动 | 0 | 1 |
串口烧写模式 | 1 | 0 |
如果你的开发板不能下载程序,把boot0 置高,然后boot1置0 ,随便找个bin文件或者使用IDE调试一下,然后将boot按钮恢复成默认模式 boot0:0 boot1:1,就可以下载了。
使用Type-C USB 连接好电脑,打开sscom串口助手,就可以看到hello world的打印信息,如图:
移植TencentOS Tiny内核前,我们先准备一个简单的点灯工程,这里跟前面的步骤一样,我们先使用MCUXpresso IDE 基于RT1060 SDK生成基础工程;
通过SDK 导入 Driver examples-> igpio_led_output 示例工程,如下图:
但是这里sdk默认使用的LED的GPIO端口跟我们开发板上的不一致,我们需要使用 MCUXpresso IDE的 MCUXpresso Config Tools进行引脚配置,查阅开发板原理图,可以发现开发板上的LED接到的是RT1062 MCU的 GPIO_SD_B1_02(M3)脚,这里我们打开MCUXpresso Config Tools-> Open Pins 或者直接点击IDE界面的芯片引脚图标对GPIO进行配置,如图所示:
打开引脚配置后,我们找到左侧的引脚列表,选择GPIO_SD_B1_02(M3)引脚,配置为GPIO3_IO02,如下图
完成后点击更新源代码,IDE就会将刚才配置好的代码更新到工程,如下图所示:
也可以看到 pin_mux.c文件中GPIO的初始化代码有更新,如下图:
同时,我们修改下工程中board.h文件中LED的GPIO端口和引脚号代码,如下图
修改完成编译下载到开发板,可以看到开发板上的LED灯闪烁,这样说明我们的基础工程完成了。
提前在 TencentOS Tiny官方项目仓下载内核代码,下载地址: https://github.com/Tencent/TencentOS-tiny
拷贝如下目录的内核代码到新建的TencentOS-Tiny文件夹备用(请严格按照一下目录拷贝,不需要拷贝多余的)
一级目录 | 二级目录 | 三级目录 | 四级目录 | 五级目录 | 说明 |
---|---|---|---|---|---|
arch | arm | arm-v7m | common | TencentOS tiny 中断tick相关代码 | |
cortex-m7 | gcc | TencentOS Tiny M核调度汇编 GCC | |||
kernel | core | TencentOS tiny内核源码 | |||
hal | TencentOS tiny驱动抽象层 | ||||
pm | TencentOS tiny低功耗源码 | ||||
TOS_CONFIG | TencentOS tiny配置头文件,用户自定义,从模板修改过来 |
这里只介绍TencentOS tiny的内核移植,所以这里只需要用到 arch、kernel两个目录下的源码。
将全部内核源码复制到工程目录下,如下图:
然后我们在工程界面按F5刷新工程,就可以在源码目录看到TencentOS Tiny的内核源码了,如图所示:
接下来,我们在gpio_led_output.c添加TencentOS Tiny内核初始化和相关任务代码
void SysTick_Handler(void)
{
if (tos_knl_is_running())
{
tos_knl_irq_enter();
tos_tick_handler();
tos_knl_irq_leave();
}
}
#define TASK1_STK_SIZE 1024
k_task_t task1;
uint8_t task1_stk[TASK1_STK_SIZE];
#define TASK2_STK_SIZE 1024
k_task_t task2;
uint8_t task2_stk[TASK2_STK_SIZE];
void task1_entry(void *arg)
{
while (1) {
PRINTF("###I am task1\r\n");
tos_task_delay(2000);
}
}
void task2_entry(void *arg)
{
while (1) {
PRINTF("***I am task2\r\n");
tos_task_delay(1000);
}
}
int main(void)
{
/* Define the init structure for the output LED pin*/
gpio_pin_config_t led_config = {kGPIO_DigitalOutput, 0, kGPIO_NoIntmode};
/* Board pin, clock, debug console init */
BOARD_ConfigMPU();
BOARD_InitBootPins();
BOARD_InitBootClocks();
BOARD_InitDebugConsole();
/* Print a note to terminal. */
PRINTF("\r\n GPIO Driver example\r\n");
PRINTF("\r\n Welcome to TencentOS Tiny!\r\n");
/* Init output LED GPIO. */
GPIO_PinInit(EXAMPLE_LED_GPIO, EXAMPLE_LED_GPIO_PIN, &led_config);
tos_knl_init(); // TencentOS Tiny kernel initialize
tos_task_create(&task1, "task1", task1_entry, NULL, 4, task1_stk, TASK1_STK_SIZE, 0); // Create task1
tos_task_create(&task2, "task2", task2_entry, NULL, 3, task2_stk, TASK2_STK_SIZE, 0);// Create task2
tos_knl_start();
}
如图,需要在IDE里面配置TencentOS Tiny的编译头文件目录,按如图所示配置即可:
#ifndef _TOS_CONFIG_H_
#define _TOS_CONFIG_H_
#include "board.h" // 目标芯片头文件,用户需要根据情况更改
#define TOS_CFG_TASK_PRIO_MAX 10u // 配置TencentOS tiny默认支持的最大优先级数量
#define TOS_CFG_ROUND_ROBIN_EN 0u // 配置TencentOS tiny的内核是否开启时间片轮转
#define TOS_CFG_OBJECT_VERIFY_EN 1u // 配置TencentOS tiny是否校验指针合法
#define TOS_CFG_TASK_DYNAMIC_CREATE_EN 1u // TencentOS tiny 动态任务创建功能宏
#define TOS_CFG_EVENT_EN 1u // TencentOS tiny 事件模块功能宏
#define TOS_CFG_MMBLK_EN 1u //配置TencentOS tiny是否开启内存块管理模块
#define TOS_CFG_MMHEAP_EN 1u //配置TencentOS tiny是否开启动态内存模块
#define TOS_CFG_MMHEAP_DEFAULT_POOL_EN 1u // TencentOS tiny 默认动态内存池功能宏
#define TOS_CFG_MMHEAP_DEFAULT_POOL_SIZE 0x2000 // 配置TencentOS tiny默认动态内存池大小
#define TOS_CFG_MUTEX_EN 1u // 配置TencentOS tiny是否开启互斥锁模块
#define TOS_CFG_MESSAGE_QUEUE_EN 1u // 配置TencentOS tiny是否开启消息队列模块
#define TOS_CFG_MAIL_QUEUE_EN 1u // 配置TencentOS tiny是否开启消息邮箱模块
#define TOS_CFG_PRIORITY_MESSAGE_QUEUE_EN 1u // 配置TencentOS tiny是否开启优先级消息队列模块
#define TOS_CFG_PRIORITY_MAIL_QUEUE_EN 1u // 配置TencentOS tiny是否开启优先级消息邮箱模块
#define TOS_CFG_TIMER_EN 1u // 配置TencentOS tiny是否开启软件定时器模块
#define TOS_CFG_PWR_MGR_EN 0u // 配置TencentOS tiny是否开启外设电源管理模块
#define TOS_CFG_TICKLESS_EN 0u // 配置Tickless 低功耗模块开关
#define TOS_CFG_SEM_EN 1u // 配置TencentOS tiny是否开启信号量模块
#define TOS_CFG_TASK_STACK_DRAUGHT_DEPTH_DETACT_EN 1u // 配置TencentOS tiny是否开启任务栈深度检测
#define TOS_CFG_FAULT_BACKTRACE_EN 0u // 配置TencentOS tiny是否开启异常栈回溯功能
#define TOS_CFG_IDLE_TASK_STK_SIZE 128u // 配置TencentOS tiny空闲任务栈大小
#define TOS_CFG_CPU_TICK_PER_SECOND 1000u // 配置TencentOS tiny的tick频率
#define TOS_CFG_CPU_CLOCK (SystemCoreClock) // 配置TencentOS tiny CPU频率
#define TOS_CFG_TIMER_AS_PROC 1u // 配置是否将TIMER配置成函数模式
#endif
编译完成下载到开发板,通过串口助手我们可以看到两个任务交替运行,打印task信息,说明内核移植成功,如下图所示:
基于TencentOS Tiny EVB AIoT要完成腾讯云IoT Explorer对接,需要完成两个部分的工作。
一是:腾讯云IoT explorer 上完成项目、产品、设备创建、参数配置
二是:基于TencentOS Tiny完成终端应用开发,向腾讯云上报业务数据。
登录腾讯云物联网开发平台,点击新建项目,填写项目名称和简介:
点击项目名称进入到该项目中,点击新建产品:
产品新建成功后,可在产品列表页查看到:
进入产品,点击【物模型】,点击【导入物模型】,导入下面的JSON代码:
{
"version": "1.0",
"properties": [
{
"id": "Count",
"name": "计数器",
"desc": "",
"mode": "r",
"define": {
"type": "int",
"min": "0",
"max": "9999",
"start": "0",
"step": "1",
"unit": "n"
},
"required": false
}
],
"events": [],
"actions": [],
"profile": {
"ProductId": "JTT7WSTP6T",
"CategoryId": "1"
}
}
导入之后自动根据json文件创建的属性如下:
点击【设备调试】,进入后点击【新建设备】,创建真实设备:
创建成功之后进入设备,查看到产品ID、设备名称、设备秘钥:
对接腾讯云物联网平台需要使用网络模块,我们开发板上有WAN Interface 可以扩展wifi 4G LoRa等等,这里我们扩展一个esp8266 wifi模块,如下图所示
端侧的案例程序可以从微云下载,地址: 链接:https://share.weiyun.com/N299vYzD 密码:wsuwsx
下载完成后解压工程,然后使用 MCUXpresso IDE 导入已有工程,具体操作如下:
完成导入后,可以看到对应的工程,如图所示:
打开工程后进入 < NXP_RT1062_TencentOS_Tiny_AIoT\source\mqttclient_iot_explorer.c> 源文件,根据您的网络环境和云端创建的产品设备信息修改终端参数。
找到mqttclient_task函数,修改要接入WIFI的名称和密码(建议使用手机热点,不要有特殊字符):
终端的MQTT客户端需要对应的产品ID、设备ID,密码,我们从云端获取到对应的信息备用,如下图所示:
获取到云端设备的产品ID、设备名称、设备密钥三元组后,我们使用如下的python脚本来生成mqtt 用户名 密码等信息:
python脚本如下,也可以到https://github.com/OpenAtomFoundation/TencentOS-tiny/blob/master/tools/mqtt_config_gen.py 获取。
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import base64
import hashlib
import hmac
import random
import string
import time
from string import Template
# bind raw_input to input in Python 2
try:
input = raw_input
except NameError:
pass
product_id = input("product id:")
dev_name = input("device name:")
passwd = input("password:")
sub = input("subscribe topic:[default:control]")
if sub == "":
sub = "control"
pub = input("publish topic:[default:event]")
if pub == "":
pub = "event"
client_id = product_id + dev_name
# expire time: 2^32 - 1 = 4294967295
username = client_id+";21010406;12365;{}".format(4294967295)
def hmacsha1(content, passwd):
passwd_byte = base64.b64decode(passwd)
return hmac.new(passwd_byte, content, digestmod=hashlib.sha1).hexdigest()
username = username.encode("utf-8")
passwd = passwd.encode("utf-8")
sign = hmacsha1(username, passwd)
template_header = ('#ifndef TOS_MQTT_CONFIG_H\n'
'#define TOS_MQTT_CONFIG_H\n'
'\n'
'#define MQTT_SERVER_IP "111.230.189.156"\n'
'#define MQTT_SERVER_PORT "1883"\n'
'#define MQTT_PRODUCT_ID "$product"\n'
'#define MQTT_DEV_NAME "$dev"\n'
'#define MQTT_CLIENT_ID "$product$dev"\n'
'#define MQTT_USR_NAME "$product$dev;21010406;12365;4294967295"\n'
'#define MQTT_PASSWORD "$sign;hmacsha1"\n'
'#define MQTT_SUBSCRIBE_TOPIC "$product/$dev/$sub"\n'
'#define MQTT_PUBLISH_TOPIC "$product/$dev/$pub"\n'
'\n'
'#define MQTT_SERVER_DOMAIN "$product.iotcloud.tencentdevices.com"\n'
'#define MQTT_TOPIC "$product/$dev"\n'
'#define MQTT_SUBSCRIBE_TOPIC_DOWN "$thing/down/property/$product/$dev"\n'
'#define MQTT_PUBLISH_TOPIC_UP "$thing/up/property/$product/$dev"\n'
'\n'
'#endif\n'
'\n')
template_c = ('#ifndef TOS_MQTT_CONFIG_H\n'
'tos_sal_module_parse_domain(MQTT_SERVER_DOMAIN,host_ip,sizeof(host_ip));\n'
'\n'
'mqtt_set_port(client, MQTT_SERVER_PORT);\n'
'mqtt_set_host(client, host_ip);\n'
'mqtt_set_client_id(client, MQTT_CLIENT_ID);\n'
'mqtt_set_user_name(client, MQTT_USR_NAME);\n'
'mqtt_set_password(client, MQTT_PASSWORD);\n'
'mqtt_set_clean_session(client, 1);\n'
'\n'
'error = mqtt_subscribe(client, MQTT_SUBSCRIBE_TOPIC_DOWN, QOS0, tos_topic_handler);\n'
'\n'
'error = mqtt_publish(client, MQTT_PUBLISH_TOPIC_UP, &msg);\n'
'\n'
'#endif\n'
'\n')
src_header = Template(template_header)
src_c = Template(template_c)
d = {
'product':product_id,
'dev':dev_name,
'sign':sign,
'sub':sub,
'pub':pub,
'thing':'$thing'
}
#do the substitution
dst_header = src_header.substitute(d)
dst_c = src_c.substitute(d)
print("===============Generate mqtt_config.h==================")
print(dst_header)
with open('mqtt_config.h', 'w') as f:
f.write(dst_header)
print("===============Generate mqtt_connect_demo.c==================")
print(dst_c)
with open('mqtt_connect_demo.c', 'w') as f:
f.write(dst_c)
运行python脚本,一次输入产品ID、设备名称、设备密钥,就可以生成对用的mqtt信息了,如下图所示:
然后我们根据生成的mqtt 客户端信息修改mqttclient_task函数,需要修改的内容如下:
最新版本的mqtt_config_gen.py将同时生成mqtt_config.h、mqtt_connect_demo.c文件,引入mqtt_config.h后,可直接复制mqtt_connect_demo.c中的示例代码,到mqttclient_task函数之中对应的部分。
工程上右键,选择构建项目,编译整个工程:
工程右键,选择调试方式,进入MCUXpresso IDE LinkServer CMSIS DAP ,下载程序到开发板并进行调试:
运行sscom软件,打开电脑上开发板对应的串口,比如我选择COM6,点击【打开串口】: 按下开发板上的复位键,程序开始运行,即可在串口助手中看到系统运行打印的日志:
从日志中可以看到wifi连接成功,mqtt对接腾讯云物联网平台成功;
同时数据上传成功也会出现如下日志:
回到腾讯云物联网开发平台,可以看到设备状态变为【在线】:
点击【设备日志】一栏,可以看到设备上报的计数值:
点击【设备属性】一栏,点击【计数器】后的【查看】,即可看到计数值的历史数据曲线图:
手机端在【微信】搜索【腾讯连连】小程序,首次使用需要进入后点击【我的】->【家庭管理】,添加一个你喜欢的名称即可。
返回【首页】,点击右上角“加号”图标:
进入后点击右上角扫码图标:
在腾讯云物联网开发平台进入【设备调试】,点击对应设备后的【二维码】:
腾讯连连扫描此二维码即可成功添加设备,添加成功之后如图:
点击此设备即可实时查看数据,并下发控制指令:
写在结尾的话:感谢大家使用TencentOS Tiny,本文难免有描述不清晰的地方,如果有任何问题,欢迎加入TencentOS Tiny 的官网QQ技术群进行交流,基于TencentOS Tiny相关的项目合作请邮件联系 supowang@tencent.com