硬件平台:STM32F103+CC3000 软件平台:MDK Keil 4.22 现象描述:参考国产某开发板,将其提供的代码移植到自家平台上。开始以为只是引脚定义不同,对比电路图稍做修改后。最后程序似乎跑起来了,比如灯闪了。连续跑了几次,偶尔会能够Smart Config,感觉很奇怪;即使能Config成功,通过PC工具却收不到板子发出来的数据。 通过网络,终于看到了这样一篇博文《CC3000驱动移植中的几个陷阱》,我已经转到EDNChina,详见http://bbs.ednchina.com/BLOG_ARTICLE_3024084.HTM. 其中的第二部分,那几个函数是关键。 SpiPauseSpi函数是暂时挂起IO口外部中断,也就是IRQ下降沿中断,如果在SpiPauseSpi调用之后,IRQ线上再有下降沿,该中断将一直保持Pending状态,暂时不调用中断服务程序,该中断必须在调用SpiResumeSpi被重新响应,而不能被丢弃。 |
下面是TI提供的MSP430+CC3000例程中,对这部分功能的实现。乍一看去,感觉没什么,但仔细一看,不知所去。而且注释部分,也没什么有价值的信息。 //***************************************************************************** //! SpiPauseSpi //! //! @param none //! //! @return none //! //! @brief Spi pause operation //***************************************************************************** void SpiPauseSpi(void) { SPI_IRQ_PORT &= ~SPI_IRQ_PIN; } //***************************************************************************** //! SpiResumeSpi //! //! @param none //! //! @return none //! //! @brief Spi resume operation //***************************************************************************** void SpiResumeSpi(void) { SPI_IRQ_PORT |= SPI_IRQ_PIN; } 这两个函数实现的功能,比较另类,是让中断处于和跳出Pending状态。说白了,SpiPauseSpi()实现的是中断来了,挂在那里,不去理会,不去调用中断服务子程序;等调用SpiResumeSpi()函数了,再去处理,注意,中断并没有被抛弃。正如博文《CC3000驱动移植中的几个陷阱》所言,STM32的标准库里面并没有该中断功能的实现,所以参考文档PM0056——STM32F10xxx/20xxx/21xxx/L1xxxx Cortex-M3 programming manual(该文档也附在后面),重新编写了函数,如下所示。 void SpiPauseSpi(void) { NVIC->ISPR[0] = (1 << (IRQ_INT_CHANNEL)); } void SpiResumeSpi(void) { NVIC->ICPR[0] = (1 << (IRQ_INT_CHANNEL)); } 这里NVIC为嵌套向量中断控制器(Nested Vectored Interrupt Controller)寄存器组的结构体。 struct { __IO uint32_t ISER[8]; /*!< Offset: 0x000 (R/W) Interrupt Set Enable Register*/ uint32_t RESERVED0[24];__IO uint32_t ICER[8]; /*!< Offset: 0x080 (R/W) Interrupt Clear Enable Register*/ uint32_t RSERVED1[24];__IO uint32_t ISPR[8]; /*!< Offset: 0x100 (R/W) Interrupt Set Pending Register*/ uint32_t RESERVED2[24];__IO uint32_t ICPR[8]; /*!< Offset: 0x180 (R/W) Interrupt Clear Pending Register*/ uint32_t RESERVED3[24];__IO uint32_t IABR[8]; /*!< Offset: 0x200 (R/W) Interrupt Active bit Register */ uint32_t RESERVED4[56];__IO uint8_t IP[240]; /*!< Offset: 0x300 (R/W) Interrupt Priority Register (8Bit wide) */ uint32_t RESERVED5[644];__O uint32_t STIR; /*!< Offset: 0xE00 ( /W) Software Trigger Interrupt Register*/ }; 用到的是ISPR和ICPR,分别是Interrupt Set Pending Register和Interrupt Clear Pending Register,从名称就可以看出这两个寄存器组的功能,它们分别有三组寄存器ISPR[0]~[2]和ICPR[0]~[2]. 在我们的产品中,SPI的中断是通过外部中断CC3000的SPI_IRQ接在STM32的GPIO PB1上实现的。PB1对应的外部中断1,在STM3210X.h中,EXTI1_IRQn = 7,即前面程序中IRQ_INT_CHANNEL为7(EXTI1_IRQn),注意,EXTI1_IRQn是中ISPR[0]和ICPR[0]中的,如果用了比如用到EXTI15_10_IRQn,那应该是在ISPR[1]和ICPR[1]中了。 这两个函数应该是CC3000移植过程中的大坑,坑填好了,目前程序运转正常。
参考文献:
1. http://bbs.ednchina.com/BLOG_ARTICLE_3024084.HTM
|