1前言
contiki是一款非常有意思的无线传感网络操作系统。认真学习了一段时间,跟踪了contiki的发展深知国内和国外在无线传感网方面的差距(这个以后可以慢慢分析)。contiki中支持的平台很多,但是和国内的情况差别较大。国人喜欢使用STM32,无线芯片多使用CC1100或SI4432,这就使得很难把contiki支持的平台直接拿来使用,需要经过很多步骤的修改。但是contiki的资料太少,国内缺少对contiki的研究和使用。本文简要分析contiki的SPI模块,SPI模块是STM32和无线芯片例如CC2520或CC1100或SI4432的重要接口。
2.SPI宏定义
contiki源码的特点便是宏定义多,很多时候找不到该宏在哪里定义,如果把这个宏理解为开关的话真不知道关闭这个宏会发生什么可怕的事情。
#ifndef __SPI_H__
#define __SPI_H__
#ifdef SPI_WAITFORTxREADY
#define SPI_WAITFORTx_BEFORE() SPI_WAITFORTxREADY()
#define SPI_WAITFORTx_AFTER()
#define SPI_WAITFORTx_ENDED() SPI_WAITFOREOTx()
#else /* SPI_WAITFORTxREADY */
#define SPI_WAITFORTx_BEFORE()
#define SPI_WAITFORTx_AFTER() SPI_WAITFOREOTx()
#define SPI_WAITFORTx_ENDED()
#endif /* SPI_WAITFORTxREADY */
extern unsigned char spi_busy;
void spi_init(void);
/* Write one character to SPI */
#define SPI_WRITE(data) \
do { \
SPI_WAITFORTx_BEFORE(); \
SPI_TXBUF = data; \
SPI_WAITFOREOTx(); \
} while(0)
/* Write one character to SPI - will not wait for end
useful for multiple writes with wait after final */
#define SPI_WRITE_FAST(data) \
do { \
SPI_WAITFORTx_BEFORE(); \
SPI_TXBUF = data; \
SPI_WAITFORTx_AFTER(); \
} while(0)
/* Read one character from SPI */
#define SPI_READ(data) \
do { \
SPI_TXBUF = 0; \
SPI_WAITFOREORx(); \
data = SPI_RXBUF; \
} while(0)
/* Flush the SPI read register */
#define SPI_FLUSH() \
do { \
SPI_RXBUF; \
} while(0);
#endif /* __SPI_H__ */
3.platform-conf.h中SPI宏定义
contiki中有两个至关重要的头文件,一个是contiki-conf.h,一个便是platform-conf.h。该头文件中存在所有和平台有关的宏定义,其中包括SPI接口。下面列举两个平台SPI定义。
【MSP430平台(exp5438)】
#define SPI_TXBUF UCB0TXBUF
#define SPI_RXBUF UCB0RXBUF
/* USART0 Tx ready? */
#define SPI_WAITFOREOTx() while ((UCB0STAT & UCBUSY) != 0) // 发送或接收正在尽心 UCBUSY置位
/* USART0 Rx ready? */
#define SPI_WAITFOREORx() while ((UCB0IFG & UCRXIFG) == 0) // 当RXBUF接收到一个字符,UCRXIFG置位
/* USART0 Tx buffer ready? */
#define SPI_WAITFORTxREADY() while ((UCB0IFG & UCTXIFG) == 0) // 当TXBUF为空时,UCTXIFG置位
【AVR平台(micaz)】
#define SPI_TXBUF SPDR
#define SPI_RXBUF SPDR
#define SPI_WAITFOREOTx() do { while (!(SPSR & BV(SPIF))); } while (0)
#define SPI_WAITFOREORx() do { while (!(SPSR & BV(SPIF))); } while (0)
说明
1.spi.h中的开头的SPI_WAITFORTxREADY和SPI_WAITFORTxREADY()并不是同一个东西,用国人熟知的内容来说,前者是常数宏,后者是动作宏。但是翻遍整个contiki的makefile文件和h文件并没有找到该定义
2.SPI_WAITFOREOTx()为等待发送完成,MSP430F5438检测忙碌标志,Atmeg128检测发送接收完成标志位
3.SPI_WAITFOREORx()为等待接收完成,MSP430F5438检测接收缓冲区标志位,Atmeg128检测发送接收完成标志
4.SPI_WAITFORTxREADY()并没有在SPI.h的其他地方使用,但是CC2520.h使用到该动作宏,SPI_WRITE_FAST之后。由于SPI_WRITE_FAST等待了发送完成,所以SPI_WAITFORTxREADY()可以定义为空,或者定义为SPI发送完成相关操作。(contiki中有非常多的宏定义,提高的移植的灵活性,但是也使得阅读代码更加复杂)
5.如果没有定义SPI_WAITFORTxREADY(找遍所有的makefile和h文件也没有找到),那么SPI_WAITFORTx_AFTER()被定义为SPI_WAITFOREOTx(),意味等待发送完成。
4.SPI宏定义展开
那么EXP5438的SPI可详细描述为:
/* Write one character to SPI */
#define SPI_WRITE(data) \
do { \
SPI_WAITFORTx_BEFORE(); \
SPI_TXBUF = data; \
SPI_WAITFOREOTx(); \
} while(0)
#define SPI_WRITE(data) \
do { \
\
UCB0TXBUF = data; \
while((UCB0STAT&UCBUSY)!=0); \
} while(0)
/* Write one character to SPI - will not wait for end
useful for multiple writes with wait after final */
#define SPI_WRITE_FAST(data) \
do { \
SPI_WAITFORTx_BEFORE(); \
SPI_TXBUF = data; \
SPI_WAITFORTx_AFTER(); \
} while(0)
#define SPI_WRITE_FAST(data) \
do { \
\
UCB0TXBUF = data; \
while((UCB0STAT&UCBUSY)!=0); \
} while(0)
/* Read one character from SPI */
#define SPI_READ(data) \
do { \
SPI_TXBUF = 0; \
SPI_WAITFOREORx(); \
data = SPI_RXBUF; \
} while(0)
#define SPI_READ(data) \
do { \
UCB0RXBUF = 0; \
while((UCB0IFG&UCRXIFG) == 0); \
data = SPI_RXBUF; \
} while(0)
5.STM32平台(假想未检验)
换句话说如果STM32连接CC2520,那么SPI几个关键定义如下(暂无硬件平台,未调试,并假设使用SPI1)
#define SPI_TXBUF SPI1->DR
#define SPI_RXBUF SPI1->DR
// 等待发送完成
#define SPI_WAITFOREOTx() while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
// 等待接收完成
#define SPI_WAITFOREORx() while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_RXNE) == RESET);
// 同为等待发送完成
#define SPI_WAITFORTxREADY() while (SPI_I2S_GetFlagStatus(SPI1, SPI_I2S_FLAG_TXE) == RESET);
6.总结
很长时间没有更新contiki方面的博文,最近才重新开始应用contiki。我猜想在国内研究无线传感网络一般就两条路,第一条研习zigbee的路线,虽然觉得这条路不一定好,但是至少很多公司都靠这个赚了钱,例如上海顺舟;另一条路便是独立开发无线传感网络协议栈,这条路比较艰辛不知能否走到终点,从而开花结果(我所在的公司选择了这条路)。还有就是contiki这条路,国外貌似越来越火,国内好像才刚刚起步。(想起看期刊论文的经历,99%的论文都说XX研究国内才刚刚起步)。呵呵,重新给contiki开个头,希望以后继续努力。
分享到:
相关推荐
Contiki学习笔记:进程、事件、etimer关系 Contiki 实例: Contiki学习笔记:创建两个交互进程 Contiki 主函数剖析: Contiki学习笔记:main函数剖析 Contiki学习笔记:启动一个进程process_start Contiki学习笔记...
Contiki适用于只有极少量内存的嵌入式系统。无线传感器网络、物联网领域应用。能够快速的入门,值得一学。
contiki学习源码及其学习笔记汇总,有助于初学者学习
摘要:本文剖析 Contiki 最简单的实例 hello_world,深入源码分析,详解了本实例用
Contiki学习笔记,很详细,可以快速的学习contiki系统,值得推荐
contiki大神jeline学习该系统的一些心得以及contiki系统的一些内核讲解
Contiki是由瑞典计算机科学研究所开发专用的网络节点操作系统,自2003年发布1.0版本以来,得到飞速发展,成为一个完整的操作系统,包括文件系统Coffee、网络协议栈uIP和Rime、网络仿真器COOJA,并于2012年发布全新...
Contiki 是一个开源的、高度可移植的多任务操作系统,适用于联网嵌入式 系统和无线传感器网络。
CC2538与contiki学习笔记(一)-附件资源
基于avr-zigduino平台的contiki学习
ContikiContiki系统学习笔记_带书签,protothread机制。
contiki学习资料源代码以及MAKEFILE等
contiki_contiki 微型操作系统介绍文档
里面是cintiki-3.0源代码的压缩文件, contiki资料非常的少,许多个人博客也都是基于该文档所写,一次该文档对于contiki学习者非常必要
Contiki是一个小型、开源、极易移植的多任务电脑操作系统。它专门设计以适用于一系列的内存受限的网络系统,...作为基础的内核以及大部分的核心功能是瑞典计算机科学研究所的网络内嵌系统小组的Adam Dunkels开发的。