编程技术分享

分享编程知识,探讨技术创新

0%

简介:一款体积很MINI的Thread 边界路由器,当然可作为ZigBee 网关,甚至可以将有线网转无线网的Wi-Fi路由器。

我将为您详细阐述这款MINI Thread 边界路由器的嵌入式系统设计架构,并提供相应的C代码示例。考虑到篇幅限制,我将尽力在保证代码质量和可读性的前提下,展示一个全面的系统框架。
关注微信公众号,提前获取相关推文

项目概述:MINI Thread 边界路由器

这款MINI Thread 边界路由器,顾名思义,其核心功能是作为Thread网络的边界路由器,连接Thread网络和IP网络(例如以太网或Wi-Fi)。同时,它还兼具ZigBee网关和Wi-Fi路由器的功能,使得它可以作为智能家居或物联网场景下的多协议互联中心。

系统架构设计:分层模块化架构

为了构建一个可靠、高效、可扩展的系统平台,我推荐采用分层模块化的架构。这种架构将系统分解为多个独立的模块,每个模块负责特定的功能,模块之间通过清晰定义的接口进行交互。这种设计方式具有以下优点:

  • 高内聚低耦合: 每个模块内部功能高度相关,模块之间依赖性低,易于维护和修改。
  • 可重用性: 模块化设计使得某些模块可以被其他项目复用,提高开发效率。
  • 可扩展性: 当需要添加新功能时,只需添加新的模块或修改现有模块,而不会对整个系统造成大的影响。
  • 易于测试: 每个模块可以独立进行单元测试,降低了系统集成测试的复杂性。
  • 并行开发: 不同的开发人员可以并行开发不同的模块,加快开发进度。

基于以上考虑,我将这款MINI Thread 边界路由器的系统架构设计为以下几个层次:

  1. 硬件抽象层 (HAL - Hardware Abstraction Layer):

    • 作用:隔离硬件差异,向上层提供统一的硬件操作接口。
    • 模块:
      • GPIO 驱动: 控制通用输入/输出引脚,例如LED指示灯、按键等。
      • UART 驱动: 用于串口通信,例如调试信息输出、命令行接口等。
      • SPI/I2C 驱动: 用于与外围芯片通信,例如传感器、存储器等。
      • 网络接口驱动: 包括以太网MAC驱动、Wi-Fi驱动、无线电收发器驱动(用于Thread和ZigBee)。
      • 定时器/PWM 驱动: 提供定时和PWM功能,用于系统定时、LED调光等。
      • 看门狗驱动: 提高系统可靠性,防止系统死机。
      • 电源管理驱动: 管理系统功耗,例如低功耗模式切换等。
      • Flash 驱动: 用于读写Flash存储器,例如存储固件、配置信息等。
  2. 操作系统层 (OS Layer):

    • 作用:提供多任务处理、任务调度、内存管理、同步机制等操作系统核心服务。
    • 组件:
      • 实时操作系统内核 (RTOS Kernel): 例如 FreeRTOS, Zephyr, RT-Thread 等,负责任务调度和资源管理。
      • 任务管理: 创建、删除、挂起、恢复任务。
      • 内存管理: 动态内存分配与释放。
      • 任务间通信 (IPC - Inter-Process Communication): 队列、信号量、互斥锁、事件标志组等,用于任务间同步和数据交换。
      • 中断管理: 处理硬件中断事件。
      • 时间管理: 提供系统时间管理功能。
  3. 网络协议栈层 (Network Stack Layer):

    • 作用:实现各种网络协议,处理网络数据包的发送和接收。
    • 模块:
      • TCP/IP 协议栈: 实现TCP/IP协议族,支持以太网和Wi-Fi网络连接。
      • Thread 协议栈: 实现Thread网络协议,例如OpenThread。
      • ZigBee 协议栈: 实现ZigBee网络协议。
      • Wi-Fi 驱动接口: 与Wi-Fi驱动交互,处理Wi-Fi连接和数据传输。
      • 以太网驱动接口: 与以太网MAC驱动交互,处理以太网连接和数据传输。
      • 网络接口管理: 管理多个网络接口,例如以太网、Wi-Fi、Thread、ZigBee。
      • 路由协议: 处理网络路由,例如IPv6路由、Thread路由、ZigBee路由。
      • 安全协议: 实现网络安全协议,例如TLS/SSL, DTLS, Thread Security, ZigBee Security。
  4. 应用服务层 (Application Service Layer):

    • 作用:实现路由器的核心功能,例如数据包转发、协议转换、设备管理、用户接口等。
    • 模块:
      • Thread 边界路由器服务: 实现Thread网络与IP网络的边界路由功能。
      • ZigBee 网关服务: 实现ZigBee网络与IP网络的网关功能。
      • Wi-Fi 路由器服务: 实现有线网络转无线Wi-Fi路由功能。
      • 数据包转发引擎: 负责数据包的接收、处理和转发。
      • 协议转换模块: 进行Thread、ZigBee、IP协议之间的转换。
      • 设备管理模块: 管理连接到路由器的设备,例如Thread设备、ZigBee设备、Wi-Fi设备。
      • 配置管理模块: 管理系统配置信息,例如网络配置、安全配置等。
      • 用户接口模块: 提供用户配置和管理路由器的接口,例如命令行接口 (CLI)、Web界面 (Web UI)。
      • OTA 升级模块: 实现固件在线升级 (Over-The-Air) 功能。
      • 日志管理模块: 记录系统运行日志,方便问题排查。
      • 安全管理模块: 处理系统安全相关的功能,例如防火墙、访问控制等。
  5. 应用层 (Application Layer):

    • 作用:基于应用服务层提供的接口,开发具体的应用程序,例如智能家居应用、物联网应用等。
    • 示例:
      • 智能家居控制应用: 通过路由器连接和控制智能家居设备。
      • 数据采集应用: 收集传感器数据并通过路由器上传到云端。
      • 远程监控应用: 通过路由器远程监控设备状态。

技术选型与方法

在这个项目中,我将采用以下经过实践验证的技术和方法:

  • 编程语言: C语言 (高效、可移植、底层控制能力强,适合嵌入式系统开发)
  • 实时操作系统 (RTOS): FreeRTOS (开源、轻量级、成熟稳定、社区活跃)
  • Thread 协议栈: OpenThread (Google 开源、符合Thread标准、功能完善、易于集成)
  • ZigBee 协议栈: 选择一款成熟的商业或开源 ZigBee 协议栈 (例如 TI Z-Stack, NXP BeeStack, 或者开源的 zigbee2mqtt 的底层库)。
  • Wi-Fi 驱动: 根据选用的Wi-Fi芯片选择相应的驱动,通常芯片厂商会提供SDK。
  • TCP/IP 协议栈: lwIP (轻量级、开源、适合资源受限的嵌入式系统)
  • 开发工具:
    • IDE: Keil MDK, IAR Embedded Workbench, Eclipse + GCC (根据目标平台和个人习惯选择)
    • 调试器: J-Link, ST-Link 等硬件调试器,配合IDE进行代码调试。
    • 版本控制: Git (管理代码版本,方便团队协作)。
    • 构建工具: CMake, Make (自动化构建过程)。
  • 开发方法:
    • 敏捷开发: 快速迭代、小步快跑、及时反馈。
    • 测试驱动开发 (TDD): 先写测试用例,再编写代码,保证代码质量。
    • 代码审查: 团队成员互相审查代码,提高代码质量和可读性。
    • 持续集成/持续交付 (CI/CD): 自动化构建、测试、部署流程,提高开发效率和交付质量。

C 代码实现示例 (框架代码,非完整实现,旨在展示架构)

为了展示上述架构,我将提供一些关键模块的C代码示例。由于篇幅限制,以下代码仅为框架代码,并非完整实现,主要用于说明架构思路和关键接口。

1. HAL 层 (HAL Layer)

  • hal_gpio.h (GPIO 驱动头文件)
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
37
38
39
40
41
42
43
44
45
46
47
48
49
#ifndef HAL_GPIO_H
#define HAL_GPIO_H

typedef enum {
GPIO_PIN_0,
GPIO_PIN_1,
GPIO_PIN_2,
// ... more pins
GPIO_PIN_MAX
} gpio_pin_t;

typedef enum {
GPIO_MODE_INPUT,
GPIO_MODE_OUTPUT
} gpio_mode_t;

typedef enum {
GPIO_LEVEL_LOW,
GPIO_LEVEL_HIGH
} gpio_level_t;

typedef struct {
gpio_pin_t pin;
gpio_mode_t mode;
// ... more configurations if needed
} gpio_config_t;

/**
* @brief 初始化 GPIO 引脚
* @param config GPIO 配置结构体
* @return 0 表示成功,非 0 表示失败
*/
int HAL_GPIO_Init(const gpio_config_t *config);

/**
* @brief 设置 GPIO 引脚输出电平
* @param pin GPIO 引脚
* @param level 输出电平
*/
void HAL_GPIO_WritePin(gpio_pin_t pin, gpio_level_t level);

/**
* @brief 读取 GPIO 引脚输入电平
* @param pin GPIO 引脚
* @return 输入电平
*/
gpio_level_t HAL_GPIO_ReadPin(gpio_pin_t pin);

#endif // HAL_GPIO_H
  • hal_gpio.c (GPIO 驱动实现,示例,需要根据具体硬件平台实现)
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
#include "hal_gpio.h"
#include "platform_hardware.h" // 假设 platform_hardware.h 中定义了硬件相关的寄存器地址和操作

int HAL_GPIO_Init(const gpio_config_t *config) {
// 根据 config 配置硬件 GPIO 寄存器
if (config->mode == GPIO_MODE_OUTPUT) {
// 配置为输出模式
GPIO_REG->MODER |= (1 << (config->pin * 2)); // 示例寄存器操作,具体根据硬件手册
GPIO_REG->MODER &= ~(1 << (config->pin * 2 + 1));
} else if (config->mode == GPIO_MODE_INPUT) {
// 配置为输入模式
GPIO_REG->MODER &= ~(1 << (config->pin * 2));
GPIO_REG->MODER &= ~(1 << (config->pin * 2 + 1));
}
// ... 其他配置,例如上拉/下拉,速度等
return 0;
}

void HAL_GPIO_WritePin(gpio_pin_t pin, gpio_level_t level) {
if (level == GPIO_LEVEL_HIGH) {
GPIO_REG->BSRR = (1 << pin); // 设置为高电平
} else {
GPIO_REG->BRR = (1 << pin); // 设置为低电平
}
}

gpio_level_t HAL_GPIO_ReadPin(gpio_pin_t pin) {
if (GPIO_REG->IDR & (1 << pin)) {
return GPIO_LEVEL_HIGH;
} else {
return GPIO_LEVEL_LOW;
}
}
  • 类似地,可以实现 hal_uart.h, hal_spi.h, hal_eth.h, hal_wifi.h, hal_radio.h 等 HAL 驱动头文件和实现。

2. 操作系统层 (OS Layer) - FreeRTOS 示例

  • main.c (主程序,初始化 RTOS,创建任务)
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#include <stdio.h>
#include "FreeRTOS.h"
#include "task.h"
#include "queue.h"
#include "semphr.h"

#include "hal_gpio.h" // 引入 HAL GPIO 驱动
#include "app_thread_border_router.h" // 引入 Thread 边界路由器应用模块
#include "app_zigbee_gateway.h" // 引入 ZigBee 网关应用模块
#include "app_wifi_router.h" // 引入 Wi-Fi 路由器应用模块

// 任务句柄
TaskHandle_t xThreadRouterTaskHandle;
TaskHandle_t xZigbeeGatewayTaskHandle;
TaskHandle_t xWifiRouterTaskHandle;
TaskHandle_t xSystemTaskHandle;

// ... 其他全局变量,例如队列、信号量等

// 系统任务:处理系统监控、日志、维护等
void SystemTask(void *pvParameters) {
(void)pvParameters;
while (1) {
// 监控系统状态
// 处理系统日志
// 执行维护任务,例如 OTA 检查
printf("System Task is running...\r\n");
vTaskDelay(pdMS_TO_TICKS(1000)); // 1秒延时
}
}

int main(void) {
// 硬件初始化 (HAL 层初始化)
gpio_config_t led_config = {GPIO_PIN_0, GPIO_MODE_OUTPUT};
HAL_GPIO_Init(&led_config);

// ... 其他 HAL 初始化,例如 UART, SPI, 网络接口等

// 创建任务
if (xTaskCreate(ThreadBorderRouterTask, "ThreadRouterTask", 2048, NULL, 3, &xThreadRouterTaskHandle) != pdPASS) {
// 任务创建失败处理
printf("Failed to create ThreadRouterTask\r\n");
}
if (xTaskCreate(ZigbeeGatewayTask, "ZigbeeGatewayTask", 2048, NULL, 2, &xZigbeeGatewayTaskHandle) != pdPASS) {
// 任务创建失败处理
printf("Failed to create ZigbeeGatewayTask\r\n");
}
if (xTaskCreate(WifiRouterTask, "WifiRouterTask", 2048, NULL, 2, &xWifiRouterTaskHandle) != pdPASS) {
// 任务创建失败处理
printf("Failed to create WifiRouterTask\r\n");
}
if (xTaskCreate(SystemTask, "SystemTask", 1024, NULL, 1, &xSystemTaskHandle) != pdPASS) {
// 任务创建失败处理
printf("Failed to create SystemTask\r\n");
}

// 启动 RTOS 调度器
vTaskStartScheduler();

// 正常情况下不会运行到这里
return 0;
}

// FreeRTOS 的钩子函数 (可选)
void vApplicationIdleHook(void) {
// 空闲任务钩子函数,可以在这里执行低功耗操作
}

void vApplicationMallocFailedHook(void) {
// 内存分配失败钩子函数,处理内存分配失败的情况
configASSERT(0); // 触发断言,停止程序运行
}

void vApplicationStackOverflowHook(TaskHandle_t xTask, char *pcTaskName) {
// 堆栈溢出钩子函数,处理堆栈溢出的情况
(void)pcTaskName;
(void)xTask;
configASSERT(0); // 触发断言,停止程序运行
}

3. 网络协议栈层 (Network Stack Layer) - 接口示例

  • network_interface.h (网络接口管理头文件,定义通用网络接口)
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
#ifndef NETWORK_INTERFACE_H
#define NETWORK_INTERFACE_H

typedef enum {
NET_IF_TYPE_ETHERNET,
NET_IF_TYPE_WIFI,
NET_IF_TYPE_THREAD,
NET_IF_TYPE_ZIGBEE,
NET_IF_TYPE_MAX
} net_if_type_t;

typedef struct net_interface {
net_if_type_t type;
char name[32];
// ... 其他接口信息,例如 MAC 地址、IP 地址等
int (*init)(struct net_interface *iface);
int (*send)(struct net_interface *iface, const void *data, size_t len);
int (*recv)(struct net_interface *iface, void *buf, size_t buf_len, size_t *recv_len);
// ... 其他接口函数,例如启动、停止、获取状态等
} net_interface_t;

// 注册网络接口
int register_net_interface(net_interface_t *iface);

// 获取网络接口
net_interface_t *get_net_interface(net_if_type_t type);

#endif // NETWORK_INTERFACE_H
  • network_interface.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
#include "network_interface.h"
#include <string.h>

#define MAX_NET_INTERFACES 4 // 最大支持的网络接口数量

static net_interface_t *g_net_interfaces[MAX_NET_INTERFACES] = {NULL};
static int g_iface_count = 0;

int register_net_interface(net_interface_t *iface) {
if (g_iface_count >= MAX_NET_INTERFACES) {
return -1; // 接口数量已满
}
g_net_interfaces[g_iface_count++] = iface;
return 0;
}

net_interface_t *get_net_interface(net_if_type_t type) {
for (int i = 0; i < g_iface_count; i++) {
if (g_net_interfaces[i]->type == type) {
return g_net_interfaces[i];
}
}
return NULL; // 未找到对应类型的接口
}
  • thread_net_interface.c (Thread 网络接口实现,示例,需要集成 OpenThread 协议栈)
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
37
38
#include "network_interface.h"
#include "openthread/thread.h" // 假设 OpenThread 头文件

static int thread_iface_init(net_interface_t *iface);
static int thread_iface_send(net_interface_t *iface, const void *data, size_t len);
static int thread_iface_recv(net_interface_t *iface, void *buf, size_t buf_len, size_t *recv_len);

net_interface_t g_thread_iface = {
.type = NET_IF_TYPE_THREAD,
.name = "thread0",
.init = thread_iface_init,
.send = thread_iface_send,
.recv = thread_iface_recv,
// ...
};

static int thread_iface_init(net_interface_t *iface) {
// 初始化 OpenThread 协议栈
// ... OpenThread 初始化代码
return 0;
}

static int thread_iface_send(net_interface_t *iface, const void *data, size_t len) {
// 使用 OpenThread 发送数据
// ... OpenThread 发送数据代码
return 0;
}

static int thread_iface_recv(net_interface_t *iface, void *buf, size_t buf_len, size_t *recv_len) {
// 使用 OpenThread 接收数据
// ... OpenThread 接收数据代码
return 0;
}

// 在系统初始化时注册 Thread 网络接口
void init_thread_net_interface(void) {
register_net_interface(&g_thread_iface);
}
  • 类似地,可以实现 ethernet_net_interface.c, wifi_net_interface.c, zigbee_net_interface.c 等网络接口驱动。

4. 应用服务层 (Application Service Layer)

  • app_thread_border_router.h (Thread 边界路由器应用模块头文件)
1
2
3
4
5
6
7
8
9
10
#ifndef APP_THREAD_BORDER_ROUTER_H
#define APP_THREAD_BORDER_ROUTER_H

#include "FreeRTOS.h"
#include "task.h"

// Thread 边界路由器任务函数
void ThreadBorderRouterTask(void *pvParameters);

#endif // APP_THREAD_BORDER_ROUTER_H
  • app_thread_border_router.c (Thread 边界路由器应用模块实现,示例)
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
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
#include "app_thread_border_router.h"
#include <stdio.h>
#include "network_interface.h"
#include "lwip/api.h" // 假设使用 lwIP 协议栈

void ThreadBorderRouterTask(void *pvParameters) {
(void)pvParameters;
net_interface_t *thread_iface = get_net_interface(NET_IF_TYPE_THREAD);
net_interface_t *eth_iface = get_net_interface(NET_IF_TYPE_ETHERNET); // 假设有以太网接口

if (thread_iface == NULL || eth_iface == NULL) {
printf("Error: Thread or Ethernet interface not found!\r\n");
vTaskDelete(NULL); // 删除当前任务
}

// 初始化 Thread 边界路由器
if (thread_iface->init(thread_iface) != 0) {
printf("Error: Thread interface initialization failed!\r\n");
vTaskDelete(NULL);
}

// ... 其他边界路由器初始化,例如路由表配置、NAT 配置等

printf("Thread Border Router Task started...\r\n");

while (1) {
// 接收 Thread 网络数据包
char thread_recv_buf[128];
size_t recv_len;
if (thread_iface->recv(thread_iface, thread_recv_buf, sizeof(thread_recv_buf), &recv_len) == 0 && recv_len > 0) {
// 处理 Thread 数据包,例如转发到 IP 网络
printf("Received Thread packet, len = %zu\r\n", recv_len);
// ... 数据包处理和转发逻辑 (例如,使用 lwIP 的 raw API 或 socket API 将数据包转发到以太网接口)

// 示例:简单回显 (仅用于演示,实际应用中需要更复杂的路由逻辑)
// eth_iface->send(eth_iface, thread_recv_buf, recv_len);
}

// 接收 IP 网络数据包 (例如以太网接口)
char eth_recv_buf[128];
recv_len = 0; // 重置 recv_len
if (eth_iface->recv(eth_iface, eth_recv_buf, sizeof(eth_recv_buf), &recv_len) == 0 && recv_len > 0) {
// 处理 IP 数据包,例如转发到 Thread 网络
printf("Received Ethernet packet, len = %zu\r\n", recv_len);
// ... 数据包处理和转发逻辑 (例如,使用 lwIP 的 raw API 或 socket API 将数据包转发到 Thread 接口)

// 示例:简单回显 (仅用于演示,实际应用中需要更复杂的路由逻辑)
// thread_iface->send(thread_iface, eth_recv_buf, recv_len);
}

vTaskDelay(pdMS_TO_TICKS(10)); // 10ms 延时
}
}
  • app_zigbee_gateway.c, app_wifi_router.c 等模块类似,实现 ZigBee 网关和 Wi-Fi 路由器的应用逻辑。

5. 应用层 (Application Layer) - 示例

  • user_app.c (用户应用程序示例,基于应用服务层接口)
1
2
3
4
5
6
7
8
9
10
#include <stdio.h>
#include "app_thread_border_router.h" // 引入应用服务层接口

void UserApplication(void) {
printf("User Application started...\r\n");
// ... 用户应用程序代码,例如调用应用服务层提供的接口,控制 Thread 设备、ZigBee 设备、Wi-Fi 设备等
// ... 例如,可以通过应用服务层提供的接口,向 Thread 网络发送控制指令,控制智能家居设备
}

// 可以将 UserApplication 的初始化代码放在 main.c 的任务中,或者单独创建一个任务运行 UserApplication

测试验证和维护升级

  • 测试验证:
    • 单元测试: 针对每个模块进行独立测试,例如 HAL 驱动测试、协议栈模块测试、应用服务模块测试。
    • 集成测试: 测试模块之间的协同工作,例如网络协议栈与应用服务层的集成测试,HAL 驱动与操作系统层的集成测试。
    • 系统测试: 对整个系统进行功能测试、性能测试、稳定性测试、安全测试等。
    • 自动化测试: 使用自动化测试工具,提高测试效率和覆盖率。
  • 维护升级:
    • OTA 升级: 实现固件在线升级功能,方便远程维护和功能升级。
    • 远程监控: 实现系统运行状态远程监控,方便问题排查和维护。
    • 日志管理: 完善的日志系统,记录系统运行日志,方便故障诊断。
    • 版本控制: 使用版本控制系统管理代码,方便版本回溯和代码维护。

总结

以上代码示例和架构设计,展示了一个适用于MINI Thread 边界路由器的嵌入式系统开发框架。这个框架基于分层模块化设计,采用C语言和FreeRTOS,并集成了Thread、ZigBee、Wi-Fi和TCP/IP协议栈。通过HAL层隔离硬件差异,通过操作系统层提供多任务处理能力,通过网络协议栈层实现网络通信,通过应用服务层实现路由器的核心功能,最终通过应用层提供用户应用程序接口。

这个架构具有良好的可靠性、高效性、可扩展性和可维护性,能够满足MINI Thread 边界路由器的功能需求,并为后续的功能扩展和维护升级奠定坚实的基础。

代码量说明:

虽然以上代码示例看起来不多,但实际上,一个完整的嵌入式系统项目,包括HAL驱动的完整实现、RTOS的配置和集成、网络协议栈的详细配置和适配、应用服务层各个模块的完整逻辑、用户接口的实现、OTA升级、日志管理、安全管理等等,代码量会非常庞大。仅仅是 OpenThread 协议栈本身的代码量就非常可观,再加上 ZigBee 协议栈、Wi-Fi 驱动、TCP/IP 协议栈以及各种应用模块的代码,整个项目代码量达到甚至超过 3000 行是完全有可能的。

请注意,以上代码仅为示例框架,具体实现需要根据实际硬件平台、选用的协议栈和具体功能需求进行详细设计和开发。希望这份详细的架构设计和代码示例能够帮助您理解嵌入式系统开发的基本思路和方法。

欢迎关注我的其它发布渠道