本篇文章主要介绍兆易创新GD32F427开发板上移植OpenWSN无线协议以及搭建CPS系统。
openwsn
物联网实现了巨大的应用,如能源感知住宅或实时资产跟踪。随着这些网络越来越成熟,标准化机构已经开始对这些微型设备网络的通信方式进行标准化。
OpenWSN项目的目标是在各种软件和硬件平台上提供基于物联网标准的完整协议栈的开源实现,这种实现可以帮助学术界和工业界验证这些标准对物联网的适用性,使这些网络真正无处不在。
6TiSCH
OpenWSN首次完整的实现6TiSCH协议标准,为IEEE802.15.4e(6TiSCH)工作组(WG)在IEEE802.15.4 TSCH链路层之上进行控制平面和IP层适配的标准化工作提供了借鉴。与主流的无线通信协议(例如WiFi,zigbee,Bluetooth)不同,6TiSCH的MAC层采用TSCH(Time SlottedChannel Hopping )协议标准,所有的通信活动采用时间触发方式依次执行,在保证实时通信的同时,确保所有的通信操作均可借助时间线进行溯源,同时允许使用者自定义任务执行序列,TSCH协议的可靠性和确定性已经在wirelessHART协议中得到验证,这也预示着该协议标准将能够为时间敏感的工业网络提供新的解决思路。
这些协议包括最低配置的网络自组机制、支持安全连接过程的协商机制、分布式网络调度管理方法。在网络层,6LoWPAN框架提供无状态报头压缩协议(RFC4944)、上下文报头压缩(RFC6282、RFC8025和RFC8138)以及通过RFC4944和IETF实现的报文分段机制。由RFC8505提供邻居发现。低功耗网络路由协议(RPL)按照目标函数(RFC6552)以多跳拓扑组织网络。该套件还定义了传输路由信息(RFC6553)和启用向下源路由(RFC6654)的协议扩展。6TiSCH提供了一种机制,通过实现链路层拓扑与路由拓扑相匹配,使节点能够与其最佳连接的父节点保持同步。CoAP和OSCORE提供了支持安全连接过程以及补充堆栈的工具,实现了低开销的安全RESTful交互。
代码移植
OpenWSN首次完整的实现6TiSCH协议标准,为IEEE802.15.4e(6TiSCH)工作组(WG)在IEEE802.15.4 TSCH链路层之上进行控制平面和IP层适配的标准化工作提供了借鉴。与主流的无线通信协议(例如WiFi,zigbee,Bluetooth)不同,6TiSCH的MAC层采用TSCH(Time SlottedChannel Hopping )协议标准,所有的通信活动采用时间触发方式依次执行,在保证实时通信的同时,确保所有的通信操作均可借助时间线进行溯源,同时允许使用者自定义任务执行序列,TSCH协议的可靠性和确定性已经在wirelessHART协议中得到验证,这也预示着该协议标准将能够为时间敏感的工业网络提供新的解决思路。
为了方便移植,建议直接在github上下载openwsn-develop, 下图展示了OpenWSN的文件结构,我们主要用到图中标识的文件:
创建工程文件,并将Openwsn源码加入工程中。
bsp中主要包含Board、debugpins.c、leds.c以及加密算法(openaes.c、crytoengine.c);openstack主要包含完整协议实现。
kernel主要包含任务调度器,实现对时间及报文的处理任务的调度。
opendri包含对不同芯片的串口、传感器、计时器的兼容实现
最后添加头文件地址。
将部分库文件(uarrt,time,gpio,aes,spi,i2c(可选,主要看与开发板互联的无线芯片采用的通信协议),)及启动文件添加到bsp/board/GD32F427文件下,并实现硬件接口代码(主要实现radio.c,sctimer.c,leds.c,board.c,board_info.c,debugpins.c,spi.h/i2c.c,eui64.c,cryptoengines.c(可选,加密算法)),这里贴出leds.c文件的示例代码(由于开发板只支持2个LED外设,其余LED将通过引脚进行连接)。
#include "hal_gpio.h"
#include "leds.h"
/* LED0. */
#define LED0_GPIO_PORT GPIOI
#define LED0_GPIO_PIN GPIO_PIN_0
/* LED1. */
#define LED1_GPIO_PORT GPIOD
#define LED1_GPIO_PIN GPIO_PIN_2
/* LED2. */
#define LED2_GPIO_PORT GPIOC
#define LED2_GPIO_PIN GPIO_PIN_6
/* LED3. */
#define LED3_GPIO_PORT GPIOC
#define LED3_GPIO_PIN GPIO_PIN_9
void Delay(void);
void GPIO_Toggle(GPIO_Type * GPIOx, uint16_t pin){
GPIOx->ODR ^= pin;
}
void leds_init(void){
GPIO_Init_Type gpio_init;
/* LED0. */
gpio_init.Pins = GPIO_PIN_0;
gpio_init.PinMode = GPIO_PinMode_Out_PushPull;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOI, &gpio_init);
/* LED1. */
gpio_init.Pins = GPIO_PIN_2;
gpio_init.PinMode = GPIO_PinMode_Out_PushPull;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOD, &gpio_init);
/* LED2. */
gpio_init.Pins = GPIO_PIN_6;
gpio_init.PinMode = GPIO_PinMode_Out_PushPull;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &gpio_init);
/* LED3. */
gpio_init.Pins = GPIO_PIN_9;
gpio_init.PinMode = GPIO_PinMode_Out_PushPull;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOC, &gpio_init);
}
void leds_error_on(void){
GPIO_WriteBit(LED0_GPIO_PORT, LED0_GPIO_PIN, 0u); /* led on. */
}
void leds_error_off(void){
GPIO_WriteBit(LED0_GPIO_PORT, LED0_GPIO_PIN, 1u); /* led off. */
}
void leds_error_toggle(void){
GPIO_Toggle(LED0_GPIO_PORT, LED0_GPIO_PIN);
}
uint8_t leds_error_isOn(void){
uint8_t bitstatus = 0x00;
if(GPIO_ReadOutDataBit(LED0_GPIO_PORT, LED0_GPIO_PIN))
return bitstatus = 0x01;
else
return bitstatus = 0x00;
}
void leds_error_blink(void){}
void leds_radio_on(void){
GPIO_WriteBit(LED1_GPIO_PORT, LED1_GPIO_PIN, 0u); /* led on. */
}
void leds_radio_off(void){
GPIO_WriteBit(LED1_GPIO_PORT, LED1_GPIO_PIN, 1u); /* led off. */
}
void leds_radio_toggle(void){
GPIO_Toggle(LED1_GPIO_PORT, LED1_GPIO_PIN);
}
uint8_t leds_radio_isOn(void){
uint8_t bitstatus = 0x00;
if(GPIO_ReadOutDataBit(LED1_GPIO_PORT, LED1_GPIO_PIN))
return bitstatus = 0x01;
else
return bitstatus = 0x00;
}
void leds_sync_on(void){
GPIO_WriteBit(LED2_GPIO_PORT, LED2_GPIO_PIN, 0u); /* led on. */
}
void leds_sync_off(void){
GPIO_WriteBit(LED2_GPIO_PORT, LED2_GPIO_PIN, 1u); /* led off. */
}
void leds_sync_toggle(void){
GPIO_Toggle(LED2_GPIO_PORT, LED2_GPIO_PIN);
}
uint8_t leds_sync_isOn(void){
uint8_t bitstatus = 0x00;
if(GPIO_ReadOutDataBit(LED2_GPIO_PORT, LED2_GPIO_PIN))
return bitstatus = 0x01;
else
return bitstatus = 0x00;
}
void leds_debug_on(void){
GPIO_WriteBit(LED3_GPIO_PORT, LED3_GPIO_PIN, 0u); /* led on. */
}
void leds_debug_off(void){
GPIO_WriteBit(LED3_GPIO_PORT, LED3_GPIO_PIN, 1u); /* led off. */
}
void leds_debug_toggle(void){
GPIO_Toggle(LED3_GPIO_PORT, LED3_GPIO_PIN);
}
uint8_t leds_debug_isOn(void){
uint8_t bitstatus = 0x00;
if(GPIO_ReadOutDataBit(LED3_GPIO_PORT, LED3_GPIO_PIN))
return bitstatus = 0x01;
else
return bitstatus = 0x00;
}
void leds_all_on(void){
GPIO_WriteBit(LED0_GPIO_PORT, LED0_GPIO_PIN, 0u);
GPIO_WriteBit(LED1_GPIO_PORT, LED1_GPIO_PIN, 0u);
GPIO_WriteBit(LED2_GPIO_PORT, LED2_GPIO_PIN, 0u);
GPIO_WriteBit(LED3_GPIO_PORT, LED3_GPIO_PIN, 0u);
}
void leds_all_off(void){
GPIO_WriteBit(LED0_GPIO_PORT, LED0_GPIO_PIN, 1u);
GPIO_WriteBit(LED1_GPIO_PORT, LED1_GPIO_PIN, 1u);
GPIO_WriteBit(LED2_GPIO_PORT, LED2_GPIO_PIN, 1u);
GPIO_WriteBit(LED3_GPIO_PORT, LED3_GPIO_PIN, 1u);
}
void leds_all_toggle(void){
GPIO_Toggle(LED0_GPIO_PORT, LED0_GPIO_PIN);
GPIO_Toggle(LED1_GPIO_PORT, LED1_GPIO_PIN);
GPIO_Toggle(LED2_GPIO_PORT, LED2_GPIO_PIN);
GPIO_Toggle(LED3_GPIO_PORT, LED3_GPIO_PIN);
}
void leds_circular_shift(void){
GPIO_Toggle(LED0_GPIO_PORT, LED0_GPIO_PIN);
Delay();
GPIO_Toggle(LED0_GPIO_PORT, LED0_GPIO_PIN);
Delay();
GPIO_Toggle(LED1_GPIO_PORT, LED1_GPIO_PIN);
Delay();
GPIO_Toggle(LED1_GPIO_PORT, LED1_GPIO_PIN);
Delay();
GPIO_Toggle(LED2_GPIO_PORT, LED2_GPIO_PIN);
Delay();
GPIO_Toggle(LED2_GPIO_PORT, LED2_GPIO_PIN);
Delay();
GPIO_Toggle(LED3_GPIO_PORT, LED3_GPIO_PIN);
Delay();
GPIO_Toggle(LED3_GPIO_PORT, LED3_GPIO_PIN);
}
void leds_increment(void){}
void Delay(void){
unsigned long ik;
for(ik=0;ik<0x7fff8;ik++) ;
}
移植结果验证
这里我们借助openwsn源码中提供的单元测试代码验证移植结果:
//main.c
#include <stdint.h>
#include <stdio.h>
#include "board_init.h"
#include "leds.h"
/*
* Definitions.
*/
/*
* Variables.
*/
/*
* Declerations.
*/
void some_delay(void);
/*
* Functions.
*/
int main(void)
{
uint8_t i;
BOARD_Init();
leds_init();
printf("\r\ngpio_basic example.\r\n");
while (1)
{
// if ( GPIO_ReadInDataBit(BOARD_KEY0_GPIO_PORT, BOARD_KEY0_GPIO_PIN) ) /* key is no pressed. */
// {
// GPIO_WriteBit(BOARD_LED0_GPIO_PORT, BOARD_LED0_GPIO_PIN, 1u); /* led off. */
// GPIO_WriteBit(BOARD_LED1_GPIO_PORT, BOARD_LED1_GPIO_PIN, 0u); /* led on. */
// }
// else /* key is pressed. */
// {
// GPIO_WriteBit(BOARD_LED0_GPIO_PORT, BOARD_LED0_GPIO_PIN, 0u); /* led on. */
// GPIO_WriteBit(BOARD_LED1_GPIO_PORT, BOARD_LED1_GPIO_PIN, 1u); /* led off. */
// }
leds_error_on(); some_delay();
leds_error_off(); some_delay();
leds_error_toggle(); some_delay();
leds_error_blink(); some_delay();
// radio LED functions
leds_radio_on(); some_delay();
leds_radio_off(); some_delay();
leds_radio_toggle(); some_delay();
// sync LED functions
leds_sync_on(); some_delay();
leds_sync_off(); some_delay();
leds_sync_toggle(); some_delay();
// debug LED functions
leds_debug_on(); some_delay();
leds_debug_off(); some_delay();
leds_debug_toggle(); some_delay();
// all LED functions
leds_all_off(); some_delay();
leds_all_on(); some_delay();
leds_all_off(); some_delay();
leds_all_toggle(); some_delay();
// LED increment function
leds_all_off(); some_delay();
for (i=0;i<9;i++) {
leds_increment(); some_delay();
}
// LED circular shift function
leds_all_off(); some_delay();
leds_error_on(); some_delay();
for (i=0;i<9;i++) {
leds_circular_shift(); some_delay();
}
}
}
void some_delay(void) {
volatile uint16_t delay;
for (delay=0xffff;delay>0;delay--);
}
在之前的文章中介绍了将ucos-ii移植到GD32F310开发板上的操作指导,为了构建将传感、驱动和计算组件紧密集成到分布式反馈回路的网络物理系统(CPS),我们将尝试分别将运行OS的GD32F310和OpenWSN的GD427V借助于BLOT协议实现互联,组件完整的CPS系统。