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协议中得到验证,这也预示着该协议标准将能够为时间敏感的工业网络提供新的解决思路。
代码移植
openWSN开发组充分考虑了协议的可移植性,通过定义统一的硬件接口头文件实现通信协议与硬件驱动进行隔离,开发者只需要实现头文件定义的协议使用的timer、radio、LED、AES、uart以及调试接口(用于观察电信号)硬件接口函数即可,着极大的方便了代码在不同硬件平台上的移植,下图展示的是openwsn代码结构及调用关系。
为了方便移植,建议直接在github上下载openwsn-develop, 下图展示了OpenWSN的文件结构,我们主要用到图中标识的文件。
创建工程文件,并将Openwsn源码加入工程中。
添加头文件地址。
将MM32F5270的部分库文件(uarrt,time,gpio,aes,spi,i2c(可选,主要看与开发板互联的无线芯片采用的通信协议),)及启动文件添加到bsp/board/Plus-5270文件下,并实现硬件接口代码(主要实现radio.c,sctimer.c,leds.c,board.c,board_info.c,debugpins.c,spi.h/i2c.c,eui64.c,cryptoengines.c(可选,加密算法)),这里贴出leds.c和board.h文件的代码。
//leds.c
#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 GPIOB
#define LED2_GPIO_PIN GPIO_PIN_14
/* 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_14;
gpio_init.PinMode = GPIO_PinMode_Out_PushPull;
gpio_init.Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &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++) ;
}
//board_info.h
#ifndef __BOARD_INFO_H
#define __BOARD_INFO_H
#include "stdint.h"
#include "string.h"
//=========================== defines =========================================
//TODO in case previous declaration fails in certain compilers. Remove this
//one if it works with GNU GCC
//#define PACK_START _Pragma("pack(1)")
//#define PACK_END _Pragma("pack()")
#define INTERRUPT_DECLARATION(); //no declaration
#define DISABLE_INTERRUPTS() // NVIC_SETPRIMASK();
#define ENABLE_INTERRUPTS() // NVIC_RESETPRIMASK();
//===== timer
#define PORT_TIMER_WIDTH uint32_t
#define PORT_RADIOTIMER_WIDTH uint32_t
#define PORT_SIGNED_INT_WIDTH int32_t
#define PORT_TICS_PER_MS 32
#define SCHEDULER_WAKEUP() //EXTI->SWIER |= EXTI_Line1;
#define SCHEDULER_ENABLE_INTERRUPT() //enable in board use EXTI_Line1
// this is a workaround from the fact that the interrupt pin for the GINA radio
// is not connected to a pin on the MSP which allows time capture.
//#define CAPTURE_TIME() TACCTL2 |= CCIS0; \
// TACCTL2 &= ~CCIS0;
//===== pinout
// [P4.7] radio SLP_TR_CNTL
#define PORT_PIN_RADIO_SLP_TR_CNTL_HIGH() // GPIOB->ODR |= 0X0002;
#define PORT_PIN_RADIO_SLP_TR_CNTL_LOW() // GPIOB->ODR &= ~0X0002;
// radio reset line
// radio /RST
#define PORT_PIN_RADIO_RESET_HIGH() //GPIOC->ODR |= 0X0040;
#define PORT_PIN_RADIO_RESET_LOW() //GPIOC->ODR &= ~0X0040;
//===== IEEE802154E timing
#define SLOTDURATION 20 // in miliseconds
// time-slot related
#define PORT_TsSlotDuration 655 // counter counts one extra count, see datasheet
// execution speed related
#define PORT_maxTxDataPrepare 66 // 2014us (measured 746us)
#define PORT_maxRxAckPrepare 20 // 305us (measured 83us)
#define PORT_maxRxDataPrepare 33 // 1007us (measured 84us)
#define PORT_maxTxAckPrepare 30 // 305us (measured 219us)
// radio speed related
#define PORT_delayTx 10 // 214us (measured 219us)
#define PORT_delayRx 0 // 0us (can not measure)
// radio watchdog
//===== adaptive_sync accuracy
#define SYNC_ACCURACY 2 // ticks
//=========================== typedef ========================================
//=========================== variables =======================================
static const uint8_t rreg_uriquery[] = "h=ucb";
static const uint8_t infoBoardname[] = "PLUS-F5270";
static const uint8_t infouCName[] = "MM32F5270";
static const uint8_t infoRadioName[] = "AT86RF231";
//=========================== prototypes ======================================
//=========================== public ==========================================
//=========================== private =========================================
#endif
移植结果验证
这里我们借助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--);
}
视频链接:https://www.bilibili.com/vide...
总结
该工作目前只完成了部分硬件接口的移植,后续将继续完善开发板支持的所有硬件驱动代码,以及评估开发板对openwsn协议代码的支持及运行性能。