查看: 1710|回复: 0

CC3000驱动移植过程的一个大坑

[复制链接]
  • TA的每日心情
    开心
    2018-10-31 10:17
  • 签到天数: 447 天

    连续签到: 1 天

    [LV.9]以坛为家II

    发表于 2014-9-23 06:42:40 | 显示全部楼层 |阅读模式
    分享到:

    硬件平台: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

    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    手机版|小黑屋|与非网

    GMT+8, 2024-11-27 00:18 , Processed in 0.113074 second(s), 15 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.