contiki学习笔记 spi部分解析

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_WAITFORTxREADYSPI_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开个头,希望以后继续努力。


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值