请选择 进入手机版 | 继续访问电脑版
查看: 2213|回复: 3

[原创] i.MX RT1060 软件复位讨论

[复制链接]

该用户从未签到

648

主题

6301

帖子

0

超级版主

Rank: 8Rank: 8

积分
19541
最后登录
2024-3-28
发表于 2021-5-15 09:06:59 | 显示全部楼层 |阅读模式
本帖最后由 小恩GG 于 2021-5-15 09:13 编辑

背景介绍

在嵌入式开发中,我们会不时用到软件复位来让系统重新启动,软件复位有别于POR(上电复位)和Reset引脚等需依赖硬件电路的硬件复位,它完全是基于代码实现, 其中Cortex-M核 MCU实现软件复位的方式大致如下:

  • 调用NVIC_SystemReset()函数;
  • 开门狗软件复位;
  • 芯片原厂提供的软件复位方式;

本篇分享源于客户的真实案例,客户尝试了上述的所有软件复位方式,仍无法成功复位MCU。

注:客户的开发板为:Embedded Artist RT1062 OEM board,其中的板载QSPI: Adesto ATXP032

c7235679-fad2-45b9-9a07-364f72d8e697.png

图1 Embedded Artist RT1062 OEM board

问题真相

经过前期的测试后,客户发现在执行软件复位后,RT1060应该被‘困’在了解i.MXRT1060系列ROM中串行NOR Flash启动初始化流程优化点所介绍的从FlexSPI NOR启动初始化流程中了(如图2所示)。

2021-05-14_17-11-42.png

图2

最后,经过反复实验发现软件复位失败是由于在对RT1060进行软件复位时,未能同步对 ATXP032进行专门的复位操作引起的,那么该如何对其进行复位操作呢?

复位ATXP032
  • JEDEC标准复位

JEDEC复位指主机MCU发送序列信号到Flash设备并导致Flash设备上复位。主机MCU通过两个SPI接口引脚发送该序列信号(如下图所示)。

4ab3dad3-2d62-4f35-a866-ea7339fdeb23.png

图 3

注:JEDEC标准复位仅针对于Adesto ATXP系列为代表的Flash

  • Reset 引脚

跟MCU中Reset 引脚功能类似(如下图所示),拉低Reset 引脚也将复位ATXP032。

538ed76d-fb73-4653-9bfd-160a25df373f.png

图4 Reset 引脚

‘改造’NVIC_SystemReset()函数

通过Reset 引脚拉低来复位,本质上也是属于硬件复位,需要依赖电路,在这里就不做过多的讨论,而此篇的着眼点在于如何通过软件实现JEDEC标准复位。 由于core_cm7.h中的NVIC_SystemReset()函数(如下所示)未能成功实现软件复位,

  1. void NVIC_SystemReset(void)
  2. {
  3.   __DSB();                                                          /* Ensure all outstanding memory accesses included
  4.                                                                        buffered write are completed before reset */
  5.   SCB->AIRCR  = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos)    |
  6.                            (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
  7.                             SCB_AIRCR_SYSRESETREQ_Msk    );         /* Keep priority group unchanged */
  8.   __DSB();                                                          /* Ensure completion of memory access */

  9.   for(;;)                                                           /* wait until reset */
  10.   {
  11.     __NOP();
  12.   }
  13. }
复制代码

故需要‘改造’ 此函数,结合Embedded Artist RT1062 OEM board的连接ATXP032设计(如下表所示),手动实现图3所示的时序信号来触使ATXP032复位,具体代码如下:

2021-05-15_9-12-30.png

表1

  1. /*
  2. * JEDEC reset of external serial flash in three steps:
  3. * 1) Disable interrupts and the data cache
  4. * 2) Do the JEDEC reset sequence
  5. * 3) Issue the NVIC_SystemReset() to do the actual reset
  6. *
  7. * Note: This function must be executing in RAM.
  8. * Note: The NVIC_SystemReset() call may take up to 3s to complete
  9. *       depending on compiler and Debug/Release build
  10. * Note: Function call only valid for targets running in/from
  11. *       flash - not for targets running in debugger and/or in RAM
  12. */
  13. __attribute__((section("RamFunction")))
  14. void Updated_NVIC_SystemReset(void)
  15. {
  16. #define CS  (1<<6)
  17. #define SCK (1<<7)
  18. #define SI  (1<<8)
  19. #define RESETMASK   (CS|SCK|SI)
  20. #define IGNOREPINS  ((1<<9)|(1<<10)|(1<<11)|(1<<1)|(1<<2)|(1<<3))
  21. #define LOW(__mask)   GPIO3->DR &= ~(__mask)  /* Set pin output to low level.*/
  22. #define HIGH(__mask)  GPIO3->DR |=  (__mask)  /* Set pin output to high level.*/

  23.     __disable_irq();
  24.     SCB_DisableDCache();

  25.     /* Configure CS/SCK/SI as outputs and the other flexspi pins as inputs */
  26.     CLOCK_EnableClock(kCLOCK_Gpio3);
  27.     GPIO3->IMR &= ~(RESETMASK | IGNOREPINS);
  28.     GPIO3->GDIR |= (RESETMASK);
  29.     GPIO3->GDIR &= ~(IGNOREPINS);

  30.     IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_06_GPIO3_IO06,0);
  31.     IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_07_GPIO3_IO07,0);
  32.     IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_08_GPIO3_IO08,0);
  33.     IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_09_GPIO3_IO09,0);
  34.     IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_10_GPIO3_IO10,0);
  35.     IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_11_GPIO3_IO11,0);
  36.     IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_01_GPIO3_IO01,0);
  37.     IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_02_GPIO3_IO02,0);
  38.     IOMUXC_SetPinMux(IOMUXC_GPIO_SD_B1_03_GPIO3_IO03,0);

  39.     IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_06_GPIO3_IO06, 0x10b0);
  40.     IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_07_GPIO3_IO07, 0x10b0);
  41.     IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_08_GPIO3_IO08, 0x10b0);
  42.     IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_09_GPIO3_IO09, 0x10b0);
  43.     IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_10_GPIO3_IO10, 0x10b0);
  44.     IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_11_GPIO3_IO11, 0x10b0);
  45.     IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_01_GPIO3_IO01, 0x10b0);
  46.     IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_02_GPIO3_IO02, 0x10b0);
  47.     IOMUXC_SetPinConfig(IOMUXC_GPIO_SD_B1_03_GPIO3_IO03, 0x10b0);

  48.     /* Reset sequence */
  49.     HIGH(CS);
  50.     LOW(SCK|SI);

  51.     LOW(CS);
  52.     HIGH(CS);
  53.     HIGH(SI);

  54.     LOW(CS);
  55.     HIGH(CS);
  56.     LOW(SI);

  57.     LOW(CS);
  58.     HIGH(CS);
  59.     HIGH(SI);

  60.     LOW(CS);
  61.     HIGH(CS);

  62.     /* Delay at least 110us */
  63.     for (int i = 33000; i >= 0; i--) {
  64.         __NOP();
  65.     }

  66.     /* Actual reset. This code is copied from NVIC_SystemReset() in core_cm7.h
  67.        and must be copied here as MCUXpresso IDE (only for the Debug target)
  68.        will keep the function in serial flash even if it is 'static inline'
  69.        and called from a function placed in RAM and since we have resetted
  70.        the serial flash using it results in a crash and not a reset. Manually
  71.        copying the code seems to do the trick. */
  72.     __DSB();                                                          /* Ensure all outstanding memory accesses included
  73.                                                                          buffered write are completed before reset */
  74.     SCB->AIRCR  = (uint32_t)((0x5FAUL << SCB_AIRCR_VECTKEY_Pos)    |
  75.                              (SCB->AIRCR & SCB_AIRCR_PRIGROUP_Msk) |
  76.                               SCB_AIRCR_SYSRESETREQ_Msk    );         /* Keep priority group unchanged */
  77.     __DSB();                                                          /* Ensure completion of memory access */

  78.     for(;;)                                                           /* wait until reset */
  79.     {
  80.         __NOP();
  81.     }
  82. }
复制代码



回复

使用道具 举报

  • TA的每日心情
    开心
    2023-2-28 15:37
  • 签到天数: 42 天

    [LV.5]常住居民I

    42

    主题

    500

    帖子

    0

    版主

    Rank: 7Rank: 7Rank: 7

    积分
    1369

    热心会员

    最后登录
    2024-2-23
    发表于 2021-5-17 09:51:47 | 显示全部楼层
    这个板子看着也很mini啊
    签到签到
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    648

    主题

    6301

    帖子

    0

    超级版主

    Rank: 8Rank: 8

    积分
    19541
    最后登录
    2024-3-28
     楼主| 发表于 2021-5-17 14:41:38 | 显示全部楼层
    y369369 发表于 2021-5-17 09:51
    这个板子看着也很mini啊

    对的,你可以跟一个外设板拼接起来用。
    回复 支持 反对

    使用道具 举报

    该用户从未签到

    0

    主题

    1

    帖子

    0

    新手上路

    Rank: 1

    积分
    12
    最后登录
    2024-1-2
    发表于 2021-6-11 11:12:18 | 显示全部楼层
    版主你好,我使用的是华邦的W25Q64,复位的时候程序跑飞,请问可能是什么问题?
    我有跑FreeRTOS,请问FreeRTOS下软复位需要注意些什么?
    以下是我的复位代码:
    void SoftwareReset(void)
    {
            GUI_Exit();
            DisableIRQ(SysTick_IRQn);
            for(DWORD i = 0; i < GPIO6_7_8_9_IRQn; i++)
            {//把所有中断关一遍
                    DisableIRQ((IRQn_Type)i);
            }
            __asm("CPSID   I");
           
            NVIC_SystemReset();
    }
    我也试过JEDEC复位Flash,但是还是一样跑飞。
    回复 支持 反对

    使用道具 举报

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

    本版积分规则

    关闭

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

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-3-29 00:25 , Processed in 0.124411 second(s), 23 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表