LV01-01-AliOSThings-17-代码移植-02-代码适配

本文主要是AliOSThings移植——代码适配的相关笔记,若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
Windows版本 windows11
Ubuntu版本 Ubuntu22.04的64位版本
VMware® Workstation 16 Pro 16.2.3 build-19376536
终端软件 MobaXterm(Professional Edition v23.0 Build 5042 (license))
点击查看本文参考资料
分类 网址 说明
官方网站 阿里云 阿里云官网主页
阿里生活物联平台 生活物联网平台(飞燕平台)主页
AliGenie 天猫精灵开放平台AliGenie主页
阿里物联网平台 阿里物联网平台主页
Bluetooth 技术网站 蓝牙协议规范什么的可以来这里找
Telink Telink | Chips for a Smarter IoT (telink-semi.com)
Telink中文官网
开发手册 AliOS Things开发指南 AliOS Things开发指南,这里是最新版本,可以直接从官网找到
AliOS Things开发指南 AliOS Things应用开发指南,这里应该是3.3版本的完整开发文档
AliOS Things开发指南(3.0) AliOS Things应用开发指南,这里应该是3.0版本的完整开发文档
生活物联网平台开发文档 生活物联网平台(飞燕平台)开发文档
《设备端开发指南》
Wi-Fi IoT品类定义与功能开发 天猫精灵IoT开放平台——Wi-Fi IoT品类定义与功能开发
硬件平台 mk3080 WiFi开发板 WiFi开发板使用指南-阿里云开发者社区
esp8266开发板 一个教程:ESP8266-NodeMCU开发板详解-太极创客 (taichi-maker.com)
TLSR8258 Datasheet Datasheet for Telink BLE + IEEE802.15.4 MultiStandard Wireless SoC TLSR8258
参考资料 AliOS Things 3.0 应用开发指南 这个只是一篇参考文章,里面是一些环境搭建相关的,可以参考
IP知识百科 - 华为 (huawei.com) IP的一些相关知识点
点击查看相关文件下载
分类 网址 说明
蓝牙规范相关文档 Core Specification 5.2 核心规格 5.2,该规范定义了创建可互操作的Bluetooth 设备所需的技术。
《Core_v5.2.pdf》
Mesh Model(v1.1) 本Bluetooth 规范定义了模型(以及它们所需的状态和消息),这些模型用于在mesh 网络中的节点上执行基本功能,超出了Bluetooth Mesh 配置文件 规范中定义的基础模型。
本规范包括定义跨设备类型标准功能的通用模型,以及支持关键mesh 场景的模型,如照明控制、传感器、时间和场景。
《MshMDL_v1.1.pdf》
Mesh Profile(v1.0.1) 该Bluetooth 规范定义了基本要求,以实现可互操作的mesh 网络解决方案,用于Bluetooth 低能量无线技术。
《MshPRFv1.0.1.pdf》
Mesh Device Properties 本规范包含Bluetooth Mesh 配置文件 和Bluetooth Mesh 模型规范所要求的设备属性的定义。
但是跟之前的有些区别,我主要看的之前的版本:《MMeshDeviceProperties_v1.2.pdf》
GATT Specification Supplement GATT Specification Supplement | Bluetooth® Technology Website。
好像可以在线看:《GATT Specification Supplement》
Assigned Numbers GATT的一些类型定义可以在这里找。
AliOS Things alios-things/AliOS-Things Gitee上的AliOSThings SDK源码仓库
alibaba/AliOS-Things GitHub上的AliOSThings SDK源码仓库
天猫精灵蓝牙Mesh协议栈 alibaba-archive/genie-bt-mesh-stack GitHub上的天猫精灵蓝牙Mesh协议栈源码仓库。
之前是在alibaba/genie-bt-mesh-stack这个仓库。
写笔记的时候最新提交为faf523618a6a2560090fc423222b9db80984bb7a
蓝牙Mesh设备开发指南 阿里云生活服务平台开发手册——蓝牙设备开发一节中的内容

一、CPU适配

1. 涉及的函数

主要涉及目录为: platform/arch。主要涉及以下函数:

image-20201029134315238

2. CPU适配实例分析

2.1 esp8266

我们找到这个文件:AOS_SDK_PATH/platform/arch/xtensa/lx106/port.c和AOS_SDK_PATH/platform/arch/xtensa/lx106/include/port.h文件:

image-20231211214432764

我们在port.h中就可以看到上面CPU适配的一些相关函数:

image-20231211214712078

2.1.1 开关中断

AOS_SDK_PATH/platform/arch/xtensa/lx106/include/port.h中有几个宏,如下所示,它们用于打开或者关闭中断,它们都会去操作cpsr寄存器(cpsr为CPU的状态寄存器),在临界段会用到。

1
2
3
4
5
6
7
8
9
10
11
/* int lock for spinlock */
#define cpu_intrpt_save() XTOS_SET_INTLEVEL(XCHAL_EXCM_LEVEL)
#define cpu_intrpt_restore(cpsr) XTOS_RESTORE_JUST_INTLEVEL(cpsr)

/* normal int lock (can not lock the NMI) */
#define CPSR_ALLOC() cpu_cpsr_t cpsr
#define RHINO_CPU_INTRPT_DISABLE() \
do{cpsr = cpu_intrpt_save();}while(0)
#define RHINO_CPU_INTRPT_ENABLE() \
do{cpu_intrpt_restore(cpsr);}while(0)

2.1.2 任务切换函数

我们打开AOS_SDK_PATH/platform/arch/xtensa/lx106/port.c,找到如下代码:

image-20231211220156276

这个软中断就是用来触发上下文切换的,

2.1.3 cpu_first_task_start()

我们再看一下 AOS_SDK_PATH/platform/arch/xtensa/lx106/port.c中的cpu_first_task_start()函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
/*
* See header file for description.
*/
void cpu_first_task_start(void)
{
// set pendsv and systemtick as lowest priority ISR.
// pendsv setting

/*******software isr*********/
_xt_isr_attach(ETS_SOFT_INUM, SoftIsrHdl, NULL);
_xt_isr_unmask(1 << ETS_SOFT_INUM);

/* Initialize system tick timer interrupt and schedule the first tick. */
_xt_tick_timer_init(); // 初始化sys tick(系统滴答定时器)

g_active_task[cpu_cur_get()] = g_preferred_ready_task[cpu_cur_get()];// 找到已经就绪的优先级最高的任务

// REG_SET_BIT(0x3ff2006c, BIT(4));
/* Restore the context of the first task that is going to run. */

XT_RTOS_INT_EXIT();// 开启中断——进入PendSV

/* Should not get here as the tasks are now running! */
}

2.1.4 cpu_task_stack_init()

1
2
3
4
5
6
/*
* See header file for description.
*/
// int *
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size, void *arg,
task_entry_t entry);

我们在我们再看一下 AOS_SDK_PATH/platform/arch/xtensa/lx106/port.c中可以找到cpu_task_stack_init()函数:

image-20231211221509852

这一部分是在初始化栈,注意这里一定要做对齐处理。

image-20231211221843624

2.2 rtl8710

rtl8710使用的cpu架构是Cortex-M4,我们打开AOS_SDK_PATH/platform/arch/arm/armv7m/armcc/m4,会看到如下文件:

image-20231211222056959

我们打开这个文件,会看到CPU适配相关的函数,只是这里都是汇编实现的:

image-20231211222213065

其实它同样有一个头文件:AOS_SDK_PATH/platform/arch/arm/armv7m/include/port.h,里面会有对应的函数声明。

2.2.1 开关中断

我们打开AOS_SDK_PATH/platform/arch/arm/armv7m/armcc/m4/port_s.S文件,找到这两个函数定义:

image-20231211222540344

在汇编中,R0寄存器用于放C语言函数传入的参数或者传出的参数,所以在cpu_intrpt_save()函数中,会将cpsr寄存器的内容放在R0中传出,在cpu_intrpt_restore()函数中会将cpsr寄存器的内容传入到R0中。

2.2.2 任务切换函数

我们打开AOS_SDK_PATH/platform/arch/arm/armv7m/armcc/m4/port_s.S文件,找到这两个函数定义:

image-20231211222905283

这里通过汇编来触发PendSV中断,也就是软中断。

2.2.3 cpu_first_task_start()

AOS_SDK_PATH/platform/arch/arm/armv7m/armcc/m4/port_s.S文件中有 cpu_first_task_start()的定义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
;******************************************************************************
; Functions:
; void cpu_first_task_start(void);
;******************************************************************************
cpu_first_task_start
;set PendSV prority to the lowest 配置pendSV中断优先级最低
LDR R0, =SHPR3_PRI_14
LDR R1, =PRI_LVL_PENDSV
STRB R1, [R0]

;set Systick prority to the lowest 配置systick中断优先级最低
LDR R0, =SHPR3_PRI_15
LDR R1, =PRI_LVL_SYSTICK
STRB R1, [R0]

;indicate PendSV_Handler branch to _pendsv_handler_nosave 触发pendSV,并跳转_pendsv_handler_nosave执行

MOVS R0, #0
MSR PSP, R0

;make PendSV exception pending
LDR R0, =SCB_ICSR
LDR R1, =ICSR_PENDSVSET
STR R1, [R0]

;goto PendSV_Handler
CPSIE I
B .

2.2.4 cpu_task_stack_init()

这个函数定义在AOS_SDK_PATH/platform/arch/arm/armv7m/common/port_c.c中,它是公共的函数:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
void *cpu_task_stack_init(cpu_stack_t *stack_base, size_t stack_size,
void *arg, task_entry_t entry)
{
cpu_stack_t *stk;
uint32_t temp = (uint32_t)(stack_base + stack_size);

/* stack aligned by 8 byte 栈的字节对齐*/
temp &= 0xfffffff8;
stk = (cpu_stack_t *)temp;

/* task context saved & restore by hardware: */
*(--stk) = (cpu_stack_t)0x01000000L; /* xPSR: EPSR.T = 1, thumb mode */
*(--stk) = (cpu_stack_t)entry; /* Entry Point 任务函数入口的地址赋值 */
*(--stk) = (cpu_stack_t)krhino_task_deathbed; /* R14 (LR) */
*(--stk) = (cpu_stack_t)0x12121212L; /* R12 */
*(--stk) = (cpu_stack_t)0x03030303L; /* R3 */
*(--stk) = (cpu_stack_t)0x02020202L; /* R2 */
*(--stk) = (cpu_stack_t)0x01010101L; /* R1 */
*(--stk) = (cpu_stack_t)arg; /* R0 : argument */

/* task context saved & restore by software: */
/* EXC_RETURN = 0xFFFFFFFDL
Task begin state: Thread mode + non-floating-point state + PSP */
*(--stk) = (cpu_stack_t)0xFFFFFFFDL;

*(--stk) = (cpu_stack_t)0x11111111L; /* R11 */
*(--stk) = (cpu_stack_t)0x10101010L; /* R10 */
*(--stk) = (cpu_stack_t)0x09090909L; /* R9 */
*(--stk) = (cpu_stack_t)0x08080808L; /* R8 */
*(--stk) = (cpu_stack_t)0x07070707L; /* R7 */
*(--stk) = (cpu_stack_t)0x06060606L; /* R6 */
*(--stk) = (cpu_stack_t)0x05050505L; /* R5 */
*(--stk) = (cpu_stack_t)0x04040404L; /* R4 */

return stk;
}

2.5 pendSV实现

我们来看一下AOS_SDK_PATH/platform/arch/arm/armv7m/armcc/m4/port_s.S中这个PendSV_handler:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
;******************************************************************************
; Functions:
; void krhino_pendsv_handler(void);
;******************************************************************************
PendSV_Handler
CPSID I
MRS R0, PSP
;branch if cpu_first_task_start
CMP R0, #0
BEQ _first_task_restore

;hardware saved R0~R3,R12,LR,PC,xPSR

;save context
IF {FPU} != "SoftVFP"
;if the switchout task use FPU, save the FPU regs
TST LR, #0x10
IT EQ
VSTMFDEQ R0!, {D8 - D15}
;hardware saved D0~D7, FPSCR
ENDIF

SUBS R0, R0, #0x24
STM R0, {R4-R11, LR}

;g_active_task->task_stack = context region
LDR R1, =g_active_task
LDR R1, [R1]
STR R0, [R1]

#if (RHINO_CONFIG_TASK_STACK_OVF_CHECK > 0)
BL krhino_stack_ovf_check
#endif
#if (RHINO_CONFIG_SYS_STATS > 0)
BL krhino_task_sched_stats_get
#endif

当前任务入栈:

image-20201029142126415

优先级最高任务出栈:

image-20201029142201897

跳转到优先级最高的任务中:

image-20201029142235759

二、sys tick适配代码

image-20201029141933972