15

航ರ_ರ · 2022年08月21日 · 美国

【MM32F5270开发板试用】Openwsn开源无线协议在PLUS-F5270开发板上的移植

openwsn

物联网实现了巨大的应用,如能源感知住宅或实时资产跟踪。随着这些网络越来越成熟,标准化机构已经开始对这些微型设备网络的通信方式进行标准化。

OpenWSN项目的目标是在各种软件和硬件平台上提供基于物联网标准的完整协议栈的开源实现,这种实现可以帮助学术界和工业界验证这些标准对物联网的适用性,使这些网络真正无处不在。
 title=

6TiSCH

OpenWSN首次完整的实现6TiSCH协议标准,为IEEE802.15.4e(6TiSCH)工作组(WG)在IEEE802.15.4 TSCH链路层之上进行控制平面和IP层适配的标准化工作提供了借鉴。与主流的无线通信协议(例如WiFi,zigbee,Bluetooth)不同,6TiSCH的MAC层采用TSCH(Time SlottedChannel Hopping )协议标准,所有的通信活动采用时间触发方式依次执行,在保证实时通信的同时,确保所有的通信操作均可借助时间线进行溯源,同时允许使用者自定义任务执行序列,TSCH协议的可靠性和确定性已经在wirelessHART协议中得到验证,这也预示着该协议标准将能够为时间敏感的工业网络提供新的解决思路。
 title=

代码移植

openWSN开发组充分考虑了协议的可移植性,通过定义统一的硬件接口头文件实现通信协议与硬件驱动进行隔离,开发者只需要实现头文件定义的协议使用的timer、radio、LED、AES、uart以及调试接口(用于观察电信号)硬件接口函数即可,着极大的方便了代码在不同硬件平台上的移植,下图展示的是openwsn代码结构及调用关系。
 title=

为了方便移植,建议直接在github上下载openwsn-develop, 下图展示了OpenWSN的文件结构,我们主要用到图中标识的文件。

 title=

创建工程文件,并将Openwsn源码加入工程中。
微信截图_20220821161854.png
微信截图_20220821161903.png
微信截图_20220821161910.png
微信截图_20220821161919.png
添加头文件地址。
微信截图_20220821162041.png
将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协议代码的支持及运行性能。

推荐阅读
关注数
6103
内容数
272
灵动MM32 MCU相关技术知识,欢迎关注~
目录
极术微信服务号
关注极术微信号
实时接收点赞提醒和评论通知
安谋科技学堂公众号
关注安谋科技学堂
实时获取安谋科技及 Arm 教学资源
安谋科技招聘公众号
关注安谋科技招聘
实时获取安谋科技中国职位信息