<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      痞子衡嵌入式:改動i.MXRT1xxx里IOMUXC_GPR寄存器保留位可能會造成系統異常


        大家好,我是痞子衡,是正經搞技術的痞子。今天痞子衡給大家介紹的是改動i.MXRT1xxx里IOMUXC_GPR寄存器保留位可能會造成系統異常

        痞子衡的嵌入式技術交流群里有一位非常活躍的朋友(網名:文,痞子衡已經指定他為副群主)近日向痞子衡反映了一個在i.MXRT1062應用程序里動態調整FlexRAM導致WDOG模塊工作異常的問題,經過一番排查,痞子衡發現了i.MXRT芯片系統設計里的一個小秘密,這個秘密警示我們在MCU里應盡量遵循謹慎的外設寄存器賦值法,這個寄存器謹慎賦值法是什么,痞子衡先賣個關子,文末會揭秘。痞子衡今天就將這個問題解決過程還原一下,希望對大家有所啟發:

      一、重配FlexRAM影響WDOG的表象問題

        痞子衡先交待一下問題背景,這個網友是在i.MXRT1062板子上做的測試,使用的是 \SDK_EVK-MIMXRT1060\boards\evkmimxrt1060\driver_examples\wdog\iar 例程(XiP),他對工程啟動文件和主函數改動如下:

      int main(void)
      {
          wdog_config_t config;
          BOARD_ConfigMPU();
          BOARD_InitPins();
          BOARD_BootClockRUN();
          BOARD_InitDebugConsole();
      
          PRINTF("\r\n******** System Start ********\r\n");
      
          // 使能WDOG模塊,設置Timeout時間,不啟用中斷
          WDOG_GetDefaultConfig(&config);
          // Timeout value is (0xF + 1)/2 = 8 sec.
          config.timeoutValue = 0xFU;
          WDOG_Init(DEMO_WDOG_BASE, &config);
          PRINTF("--- wdog Init done---\r\n");
      
          while (1)
          {
              // 故意不喂狗,讓WDOG超時復位系統
              //WDOG_Refresh(DEMO_WDOG_BASE);
              PRINTF(" \r\nWDOG has be refreshed!");
      
              /* Delay. */
              delay(SystemCoreClock);
          }
      }
      

        他在啟動文件 startup_MIMXRT1062.s 里將默認128KB ITCM、128KB DTCM、256KB OCRAM的FlexRAM分配調整成了256KB DTCM、256KB OCRAM(關于FlexRAM基本知識詳見痞子衡舊文 《百變星君FlexRAM》),這種FlexRAM動態調整方式僅適用XiP工程。最終運行結果里看,應用程序似乎僅運行了一次,沒有像預想得那樣重復啟動執行。

        如果在 startup_MIMXRT1062.s 里將重配FlexRAM代碼去掉,這個WDOG例程是可以正常工作的,串口助手里可以看到循環打印,所以這很容易讓人推斷出FlexRAM重配功能導致WDOG模塊工作異常了。

      二、找到程序異常的根本原因

        由于這個WDOG例程并不是完全功能異常,至少首次打印是有的,說明重配FlexRAM并沒有對程序堆棧運存等造成實質影響,啟動文件里那段重配FlexRAM代碼本身沒有邏輯問題。而打印輸出在WDOG超時時間到了之后就沒有了,看起來WDOG模塊應該是正常產生了軟復位。為了最小化代碼去定位問題,痞子衡將這個網友WDOG例程主函數修改如下,去掉WDOG相關代碼,直接用 NVIC_SystemReset() 代替。運行后發現,仍然僅有一次打印,這個實驗的意義是那段重配FlexRAM代碼會導致軟復位后程序沒法再次運行,而跟具體WDOG模塊無關。

      int main(void)
      {
          BOARD_ConfigMPU();
          BOARD_InitPins();
          BOARD_BootClockRUN();
          BOARD_InitDebugConsole();
      
          PRINTF("\r\n******** System Start ********\r\n");
      
          while (1)
          {
              NVIC_SystemReset();
          }
      }
      

        我們現在將焦點放回到重配FlexRAM那段匯編代碼本身,代碼很簡單,就是將i.MXRT芯片內部的IOMUXC_GPR->GPR17(基址0x400ac044)和IOMUXC_GPR->GPR16(基址0x400ac040)分別整體賦值為0x5555aaaa和0x00000007,單純從寄存器有效功能位定義上來看,這樣操作是沒問題的。

          LDR R0,=0x400AC044
          LDR R1,=0x5555aaaa
          STR R1,[R0]
          LDR R0,=0x400AC040
          LDR R1,=0x00000007
          STR R1,[R0]
      

        翻看手冊里關于IOMUXC_GPR->GPR17和IOMUXC_GPR->GPR16寄存器的位定義,發現IOMUXC_GPR->GPR16寄存器中有很多bit是保留位,并且其中bit21保留位默認值是1,與其他保留位默認值0不一樣。顯然 IOMUXC_GPR->GPR16 = 0x00000007 這樣的賦值語句會將其bit21誤清零,并且IOMUXC_GPR寄存器在軟復位后也不會改變其值 (參見《SystemReset不復位的GPR寄存器小結》一文)。

        難道問題是由IOMUXC_GPR->GPR16[21]保留位被誤清零導致的?死馬當活馬醫吧,我們修改一下重配FlexRAM代碼如下(兩種方式都行),將IOMUXC_GPR->GPR16[21]保持為默認1。運行后發現,異常問題解決了,串口助手里可以看到循環打印。現在我們知道了IOMUXC_GPR寄存器即使是保留位也不要輕易當用戶標志位使用,更不要輕易改變其默認值,因為SoC占用了這些位,具體用途未詳述。可以推測IOMUXC_GPR->GPR16[21]位跟系統啟動有關,并且其值的設置是在軟復位后才生效的。

      #ifdef FLEXRAM_CFG_STANDARD
          LDR R0,=0x400AC044
          MOV32 R1,0x5555aaaa
          STR R1,[R0]
          LDR R0,=0x400AC040
          LDR R1,[R0]
          ORR R1,R1,#4
          STR R1,[R0]
      #else
          LDR R0,=0x400AC044
          LDR R1,=0x5555aaaa
          STR R1,[R0]
          LDR R0,=0x400AC040
          LDR R1,=0x00200007
          STR R1,[R0]
      #endif
      

      三、MCU外設寄存器謹慎賦值法

        現在痞子衡揭秘文章開頭賣的關子,到底什么是謹慎的外設寄存器賦值法。其實可以從芯片頭文件定義里去學,假設我們有一個模塊叫PERIPH,模塊內部有一個名為REG的寄存器,這個寄存器中有功能位FUNC(單bit或者多bit),芯片頭文件中通常定義如下:

      typedef struct {
        __IO uint32_t REG;
      } PERIPH_Type;
      
      #define PERIPH_REG_FUNC_MASK  (0x4U) // 或者 (0xCU)
      #define PERIPH_REG_FUNC_SHIFT (2U)
      #define PERIPH_REG_FUNC(x)    (((uint32_t)(((uint32_t)(x)) << PERIPH_REG_FUNC_SHIFT)) & PERIPH_REG_FUNC_MASK)
      
      #define PERIPH_BASE           (0x400AC000u)
      #define PERIPH                ((PERIPH_Type *)PERIPH_BASE)
      

        謹慎寄存器賦值法的核心要義就是每次操作都只涉及一種功能位,并且不要影響其他功能位的值,就像下面代碼所示。切忌出現 PERIPH->REG = value1 | value2 | ... 這樣的一次性多個不同功能位一起賦值的操作。

        謹慎寄存器賦值法既可以避免模塊設計里不同功能位賦值有先后順序的限制問題,也可以防止誤改某些保留位默認值的異常情況發生。當然這也是有小小代價的,那就是會增加了一些代碼長度。

      // 如果PERIPH->REG[FUNC]是單bit
      PERIPH->REG |= PERIPH_REG_FUNC_MASK;
      PERIPH->REG &= ~PERIPH_REG_FUNC_MASK;
      // 如果PERIPH->REG[FUNC]是多bit
      PERIPH->REG = (PERIPH->REG & (~PERIPH_REG_FUNC_MASK)) | PERIPH_REG_FUNC(value);
      

        至此,改動i.MXRT1xxx里IOMUXC_GPR寄存器保留位可能會造成系統異常痞子衡便介紹完畢了,掌聲在哪里~~~

      歡迎訂閱

      文章會同時發布到我的 博客園主頁CSDN主頁知乎主頁微信公眾號 平臺上。

      微信搜索"痞子衡嵌入式"或者掃描下面二維碼,就可以在手機上第一時間看了哦。

      posted @ 2021-06-05 14:19  痞子衡  閱讀(696)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 欧美不卡无线在线一二三区观 | 国产精品高清一区二区三区| 婷婷久久香蕉五月综合加勒比| 丝袜a∨在线一区二区三区不卡 | 亚洲人妻系列中文字幕| 亚洲av成人一区二区三区| 日本久久一区二区三区高清| 亚洲精品日本久久一区二区三区| 国产91丝袜在线观看| 亚洲国产综合性亚洲综合性| 国产精品v片在线观看不卡| 日本一区二区三区免费播放视频站| 热久久这里只有精品国产| 中国亚州女人69内射少妇| 中文字幕第一页亚洲精品| 人妻少妇偷人精品免费看| 国产免费久久精品44| 久久波多野结衣av| 国产极品丝尤物在线观看| 啪啪av一区二区三区| 午夜精品区| 亚洲欧美自偷自拍视频图片| 国产午夜三级一区二区三| 激情亚洲专区一区二区三区| 97欧美精品系列一区二区| 日本妇人成熟免费| 西西444www高清大胆| 国语偷拍视频一区二区三区| 亚洲 日韩 在线精品| 欧洲一区二区中文字幕| 精品一区二区三区国产馆| 丁香婷婷无码不卡在线| 亚洲理论在线A中文字幕| 伊人成色综合人夜夜久久| 日韩毛片在线视频x| 日本精品极品视频在线| 亚洲综合小综合中文字幕| 国产人妻精品无码av在线| 99国产精品白浆在线观看免费| 黑巨人与欧美精品一区| 又长又粗又爽又高潮的视频|