NBIOT SDK包移植说明文档
1. 移植背景开发语言:C语言 硬件平台:STM32F10X 开发环境:KEIL MDK5.23 2. 工程目录可在该目录下的main.c下实现NBIOT的例程 在目录下实现和模组进行通信的驱动,这里实现了串口驱动 实现通信模组的驱动,这里实现了esp8266的驱动 该目录下实现各种传感器的驱动 SDK包中JSON报文格式化的接口 SDK包中加解密功能接口,暂不支持 SDK包中Lwm2m和coap协议的具体实现 SDK和ONENET平台交互的接口实现 和具体硬件平台有关的底层实现 3. 工程设置在Include Paths处添加头文件所在的路径,该路径为相对于工程所在目录的相对路径 在Preprocessor Symbols处添加条件编译选项,条件编译选项如下: - NBIOT_DEBUG – 输出sdk调试日志
- LWM2M_WITH_LOGS – 输出lwm2m相关的日志
- COAP_WITH_LOGS – 输出coap相关的日志
- NO_OS-无操作系统的时候选择
- BIG_ENDIAN – 内存模型为大字节序
- LITTLE_ENDIAN – 内存模型为小字节序
- HAVE_DTLS – 带dtls加密传输
- DTLS_WITH_LOGS – 输出dtls相关的日志
注:SDK包原版支持win和linux操作系统,STM32F10x平台本身没有操作系统,因此需要选择NO_OS,同时由于STM32属于小端系统,因此需要选择LITTLE_ENDIAN,太多的打印会导致系统变慢,扰乱协议栈的时序,从而出现各种问题,因此不建议打开所有的打印。
4. 初始化SDK运行环境与SDK运行环境相关的全局变量如下图所示,分别是统一资源定位标识符URI,NBIOT服务器地址serv_addr,以及SDK在服务器端进行注册时候需要用到的鉴权码auth_code和断点名endpoint_name。 - void nbiot_init_environment( void )
在该函数中,初始化一切和SDK包运行有关的软硬件资源,包括内存管理算法初始化、系统时钟初始化、打印串口初始化、模组通信串口初始化和模组初始化。 - void nbiot_clear_environment( void )
该函数中,需要对当前SDK包的运行环境进行一些清理的工作,包括退出当前的网络,回收内存资源等动作。 5. Socket接口的实现原SDK包使用socket接口,现在由于使用模组且没有TCP/IP协议栈,因此SDK不识别任何和socket有关的数据结构和函数接口,需要对这些内容进行移植。 { SOCKET sock; }; 在这里,将SOCKET数据类型修改int型,修改后如下所示: struct nbiot_socket_t { int sock; }; { struct sockaddr_in addr; }; 在这里将struct sockaddr_in addr 修改为char型数组,用来储存字符串形式的IP地址,修改后如下所示: struct nbiot_sockaddr_t { char addr[20]; }; - int nbiot_udp_create( nbiot_socket_t **sock )
原SDK使用该函数,为sock结构体的sock成员创建了一个实体,上下文中需要使用到该实体资源,因此该接口不需要任何的修改。 - int nbiot_udp_close( nbiot_socket_t *sock )
原SDK使用该函数,调用socket接口关闭了udp连接,这里需要使用模组提供的AT命令实现udp连接的关闭。 - int nbiot_udp_bind( nbiot_socket_t *sock,
const char *addr, uint16_t port ) 原SDK包使用该函数,调用socket接口绑定udp服务器,并实例化了sock结构体里的sock成员,因此需要屏蔽掉绑定的动作,还需要对sock结构体进行赋值,在这里赋值为1 - int nbiot_udp_connect( nbiot_socket_t *sock,
const char *addr, uint16_t port, nbiot_sockaddr_t **dest ) 原SDK包使用该函数,测试设备和UDP服务器之间的连通性,使用了模组后不需要该动作,因此屏蔽掉。
6. 数据发送接口的实现- int nbiot_udp_send( nbiot_socket_t *sock,
const void *buff, size_t size, size_t *sent, const nbiot_sockaddr_t *dest ) 原SDK包使用该函数,调用SOCKET的发送接口,采用非阻塞方式将数据发送出去,在这里则直接调用模组的串口发送接口,将数据发送至模组。 7. 数据接收接口的实现- int nbiot_udp_recv( nbiot_socket_t *sock,
void *buff, size_t size, size_t *read, nbiot_sockaddr_t **src ) 原SDK包使用该函数,调用SOCKET的接口,采用非阻塞的方式接受数据,因此为了模拟非阻塞的方式,尽量不要在该函数中采用轮询的方式来接收数据,在这里设计了一个接收缓冲区,该函数负责检查接收缓存区,如果有数据则提交给SDK包进行处理,否则立即返回。 - void USART2_IRQHandler(void)
移植后的SDK包使用串口中断的方式,以字节为单位对数据进行接收,为了区分出数据包,ESP8266必须使用非透传模式,同时在接收到一个完整的数据包后,将数据包放进缓存区中,等待SDK包的处理。具体工作流程如下:首先判断一个数据包的开始,如果是则使能接收空闲中断;当发生了接收空闲中断,意味着一个完整的数据包已经接收完成,将该数据包放进缓冲区中。 8. 系统时间的实现- time_t nbiot_time( void )
time_t 类型为long型,在原SDK包中nbiot_time函数返回的是系统当前时间,单位为秒,因此使用STM32系统提供的RTC定时器作为系统滴答定时器,nbiot_time函数读取定时器里面的值并返回。 - void nbiot_sleep( int milliseconds )
使用了RTC定时器实现了ms级别的精确延时。 9. 内存管理的实现- void *nbiot_malloc( size_t size )
- void nbiot_free( void *ptr )
为了管理sdk运行过程的内存分配与释放,抽离出以上2个接口函数,便于不同环境下采用合适的内存管理策略,现在暂时使用KEIL 微库提供的malloc函数和free函数,需要注意以下两点:
- 在工程配置中,需要选择Use MicroLIB这个选项
- 在启动文件中,将Heap_Size的大小进行合理的扩充
10. 其它- coap_content_type_t结构体成员的长度问题
在原SDK包中,使用了LINUX操作系统,默认枚举类型成员的长度为系统的字长,但在嵌入式系统中,为了节省空间,只要枚举类型成员的值不超过一个字节,则不会分配两个字节的空间。为了解决该问题,需要修改coap_content_type_t结构体,否则SDK包发送的数据会被服务器扔掉,修改过程的如下所示: 在该结构体的最后,添加一行,xxx=0xFFFF,则keil编译器会为该结构体成员分配两个字节的存储空间。
完整的Word格式文档51黑下载地址:
|