色哟哟视频在线观看-色哟哟视频在线-色哟哟欧美15最新在线-色哟哟免费在线观看-国产l精品国产亚洲区在线观看-国产l精品国产亚洲区久久

0
  • 聊天消息
  • 系統消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術視頻
  • 寫文章/發帖/加入社區
會員中心
創作中心

完善資料讓更多小伙伴認識你,還能領取20積分哦,立即完善>

3天內不再提示

應用筆記 | 關閉SPI會導致WRPERR錯誤的問題分析

STM32單片機 ? 來源:未知 ? 2023-08-10 18:45 ? 次閱讀

關鍵字:SPI,Flash,WRPERR

目錄預覽

1 引言2 問題3 問題解決4 小結

01 引言

STM32的應用中,SPI算是用的比較多的外設了,也是單片機最常見外設之一。客戶說它執行了關閉SPI的代碼,竟然會導致Flash中的WRPERR標志置位,致使應用碰到一些問題。這就奇怪了,SPI和內部Flash看起來是風馬牛不相及的事情,為什么會發生這種事呢?一起來看看吧。

02 問題

2.1 問題起源

客戶在使用STM32L072RBT6的時候,使用STM32 CubeL0庫,在程序編寫時,發現執行關閉SPI代碼時,會導致Flash的寫保護錯誤標志WRPERR置位,導致其后面準備寫EEPROM的時候,就無法對EEPROM寫入了。

客戶使用兩個標志flag1和flag2,來觀察WRPERR標志的變化。代碼如圖1所示。

bd73cac8-3769-11ee-9e74-dac502259ad0.png

圖1.用戶測試代碼

在執行這個代碼時,前面flag1還等于0,執行到flag2那句,就變成flag2等于1了,同樣地取了WRPERR標志位的值。所以客戶就懷疑執行_HAL_SPI_DISABLE()會把Flash的WRPERR標志置1了。

因為在對EEPROM編程中,需要先調用位于stm32l0xx_hal_flash.c中的FLASH_WaitForLastOperation()函數,此函數中,將會對Flash所有錯誤標志進行檢查,如果出現了錯誤,它則返回HAL_ERROR,導致后續對EEPROM的編程不會被執行。

2.2 問題重現

使用NUCLEO-L053R8來驗證客戶的這個問題。在STM32Cube_FW_L0_V1.10.0ProjectsSTM32L052R8-NucleoExamplesSPISPI_FullDuplex_ComPolling例程中直接進行修改測試。

首先,把客戶的測試代碼加到例程中SPI初始化之后的位置。如圖2所示。

bd8bde6a-3769-11ee-9e74-dac502259ad0.png

圖2.測試代碼1(位于SPI初始化之后)

編譯,并在線調試,發現并沒有出現客戶所描述的問題。如圖3所示。

bdcd1132-3769-11ee-9e74-dac502259ad0.png

圖3.測試代碼1結果(位于SPI初始化之后)

可以看到,WRPERR的值并沒有被置1,Flag1和Flag2的值也都是0。那么,為什么客戶說他那邊會有這個問題呢?

再回頭仔細看一下客戶的測試代碼,發現客戶的測試代碼中并沒有對SPI進行初始化,其_HAL_SPI_DISABLE()代碼是放在其他外設初始化之后的。

好,那么再來修改一下測試代碼,把客戶這三句測試代碼挪動到SPI初始化之前,如圖4所示。

bdf126da-3769-11ee-9e74-dac502259ad0.png

圖4.測試代碼2(位于SPI初始化之前)

編譯,并在線調試,這時,會驚奇地發現客戶所描述地問題來了。其結果如圖5所示。

be3694fe-3769-11ee-9e74-dac502259ad0.png

圖5.測試代碼2結果(位于SPI初始化之前)

可以看到,這時Flash的WRPERR標志位置1了,測試代碼中,flag2的值也跟flag1不同了。

再做一個實驗,將此處的HAL庫寫法,改成直接操作寄存器,來試一下。測試代碼變成是圖6這樣的。

be561ea0-3769-11ee-9e74-dac502259ad0.png

圖6.測試代碼3(位于SPI初始化之前,直接操作寄存器)

編譯,在線調試,這次又驚喜地發現,問題不見了。結果如圖7所示。

be9c7256-3769-11ee-9e74-dac502259ad0.png

圖7.測試代碼3結果(位于SPI初始化之前,直接操作寄存器)

三種操作,為什么只有第二種方式有問題呢?而且為什么錯的偏偏是Flash的寫保護錯誤標志WRPERR呢?接下來可以分析一下它們的反匯編代碼,看看到底是哪里出問題了。

2.3 反匯編分析

對于三種情況,把反匯編拉出來看最清楚其操作過程了。

先分析第一種情況——測試代碼位于SPI初始化之后。其反匯編如圖8所示。

bebaabb8-3769-11ee-9e74-dac502259ad0.png

圖8.測試代碼1的反匯編(位于SPI初始化之后)

從之前的Watch窗口,知道flag1的地址為 0x2000000c,flag2的地址為0x2000000d。

現在對三句C語言測試語句的反匯編語句進行解析,如下:

bed8369c-3769-11ee-9e74-dac502259ad0.png

beeb4f7a-3769-11ee-9e74-dac502259ad0.png

可以看到,這段匯編是一點問題都沒有的。

接下來,先分析第三種情況——也就是測試代碼放在SPI初始化之前,但是使用直接操作寄存器的方式。其反匯編如圖9所示。

bf20e914-3769-11ee-9e74-dac502259ad0.png

圖9.測試代碼3的反匯編(位于SPI初始化之前,直接操作寄存器)

從之前的Watch窗口,知道flag1的地址為0x2000000c,flag2的地址為0x2000000d。

現在對三句C語言測試語句的反匯編語句進行解析,如下:

bf4f4e26-3769-11ee-9e74-dac502259ad0.png

bf8ab4ac-3769-11ee-9e74-dac502259ad0.png

可以看到,這段匯編也是一點問題都沒有的。

最后,再來分析一下有問題的第二種情況,也就是測試代碼放在SPI初始化之前,但是使用_HAL_SPI_DISABLE()關閉SPI的情況。其反匯編如圖10所示。

bfa3c3c0-3769-11ee-9e74-dac502259ad0.png

圖10.測試代碼2的反匯編(位于SPI初始化之前)

從之前的Watch窗口,知道flag1的地址為0x20000008,flag2的地址為0x20000009。

現在對三句C語言測試語句的反匯編語句進行解析,如下:

bfca076a-3769-11ee-9e74-dac502259ad0.png

bfe4e65c-3769-11ee-9e74-dac502259ad0.png

可以看到,問題出在哪了?問題就出在“STR R3,[R 2]”這個語句上,這個語句在0x00000000這個位置寫值,而0x00000000此時映射的是Flash的地址0x08000000,也就是Stack Pointer的位置。如圖11和圖12所示。

c019f0a4-3769-11ee-9e74-dac502259ad0.png

圖11.0x00000000地址的數據

c04706ca-3769-11ee-9e74-dac502259ad0.png

圖12.0x08000000地址的數據

首先,這個位置本來就不應該被修改。

第二,因為沒有對Flash程序存儲器進行解鎖,就往里邊寫值,就會造成寫保護錯誤,導致WRPERR標志位置位。所以,可以明白為什么WRPERR會被置位了。

可是關鍵的問題在哪兒呢?在執行“LDR R2,[R0,#4]”這條語句時,R2本來應該是SPI2_CR1的地址,但是它竟然是0x00000000!如圖13所示。

c06c0ac4-3769-11ee-9e74-dac502259ad0.png

圖13.0x2000000c地址的數據

從Watch窗口來看一下SpiHandle的情況。如圖14所示。

c0827e80-3769-11ee-9e74-dac502259ad0.png

圖14.SpiHandle(未初始化)

從圖14可以看到,其實剛才的0x2000000c地址就是SpiHandle結構體的地址,也是SpiHandle.Instance的地址,而SpiHandle.Instance的值為0。SpiHandle.Ins tance.CR1的地址為0x0,導致顯示它裝載的值是Stack pointer的值0x20000468,這里本應該是SPI2_CR1的地址和SPI2_CR1的值。

也就是因為這里的問題,才會導致了后面的WRPERR錯誤。

2.4 代碼分析

再回到代碼這邊來看一下,有問題的代碼究竟是有什么情況。客戶的代碼主要就是一句關閉SPI的語句“_HAL_SPI_DISABLE(&SpiHandle);”。

這個語句是怎么解析的?它再stm32l0xx_hal_spi.h中解析,如圖15所示。

c0a183d4-3769-11ee-9e74-dac502259ad0.png

圖15._HAL_SPI_DISABLE函數

看到這個函數時,看到了重要的字眼——“Instance”!就明白是什么問題了,因為這個SpiHandle.Instance還沒有被初始化呢!這也說明了為什么在圖14中,看到的SpiHandle.Instance的值為0x0,而SpiHandle.Instance. CR2的值為0x20000468。關鍵就在于這個SpiHandle. Instance還沒有初始化。

所以,把客戶的測試代碼放在SPI初始化代碼之后沒有問題,就是因為這個SpiHandle.Instance已經被初始化過了。所以,它不會有問題。

03 問題解決

本來客戶的代碼就沒有必要這么寫,因為SPI都沒初始化,對它進行關閉并沒有什么意義。

如果非要在這里關閉SPI的話,那就要先對SpiHandle.Instance進行初始化才行。如圖16所示。

c0afe622-3769-11ee-9e74-dac502259ad0.png

圖16._HAL_SPI_DISABLE函數

加了“SpiHandle.Instance=SPIx;”初始化后,再跑這段代碼,就不會出現客戶所說的問題了。

現在再來看一下SpiHandle的情況。

c0cadd38-3769-11ee-9e74-dac502259ad0.png

圖17.SpiHandle(SpiHandle.Instance已初始化)

經過對SpiHandle.Instance的初始化,這里就可以看到SpiHandle.Instance的值為0x40003800了,為SPI2外設寄存器的基地址,而且可以看到SpiHandle.Instance. CR1的地址就是SPI2_CR1的地址0x40003800,值也是SPI2_CR1的值0x0了。

04 小結

在用戶代碼中,SpiHandle只是定義了SPI_HandleTypeDef結構體,其各種參數并還沒有進行實際初始化。在沒有初始化的前提下,對其進行操作時不對的,也是危險的,應該在寫代碼的時候引起重視。

使用HAL庫的時候,如果要對一個外設進行任何的操作,請務必記得它是被初始化過的。否則,出了問題可能都不一定知道。

完整內容請點擊“閱讀原文”下載原文檔。

c0e4716c-3769-11ee-9e74-dac502259ad0.png

長按掃碼關注公眾號

更多資訊,盡在STM32

點擊“閱讀原文”,可下載原文檔


原文標題:應用筆記 | 關閉SPI會導致WRPERR錯誤的問題分析

文章出處:【微信公眾號:STM32單片機】歡迎添加關注!文章轉載請注明出處。


聲明:本文內容及配圖由入駐作者撰寫或者入駐合作網站授權轉載。文章觀點僅代表作者本人,不代表電子發燒友網立場。文章及其配圖僅供工程師學習之用,如有內容侵權或者其他違規問題,請聯系本站處理。 舉報投訴
  • 單片機
    +關注

    關注

    6037

    文章

    44569

    瀏覽量

    636211
  • STM32
    +關注

    關注

    2270

    文章

    10906

    瀏覽量

    356484

原文標題:應用筆記 | 關閉SPI會導致WRPERR錯誤的問題分析

文章出處:【微信號:STM32_STM8_MCU,微信公眾號:STM32單片機】歡迎添加關注!文章轉載請注明出處。

收藏 人收藏

    評論

    相關推薦

    S32K3系列汽車級MCU應用筆記

    電子發燒友網站提供《S32K3系列汽車級MCU應用筆記.docx》資料免費下載
    發表于 12-30 15:43 ?0次下載

    S32K3xxICU應用筆記

    S32K3xxICU應用筆記
    發表于 12-30 15:38 ?0次下載

    用筆記1604:去補償運算放大器

    電子發燒友網站提供《應用筆記1604:去補償運算放大器.pdf》資料免費下載
    發表于 09-29 10:30 ?0次下載
    應<b class='flag-5'>用筆記</b>1604:去補償運算放大器

    TPS6598x沒電電池應用筆記

    電子發燒友網站提供《TPS6598x沒電電池應用筆記.pdf》資料免費下載
    發表于 09-25 10:03 ?0次下載
    TPS6598x沒電電池應<b class='flag-5'>用筆記</b>

    芯海CS32F0XXTIMER外設模塊應用筆記

    本應用筆記旨在展示使用CS32FOxx微控器,針對定時器外設的應用。幫助用戶了解CS32FOxx定時器的基本特性、操作模式及相關應用的示例代碼。提供的一些高級應用以便縮短用戶開發周期。對所介紹的特定
    發表于 05-16 15:02

    芯海CS32F0XXADC外設模塊應用筆記

    本應用筆記旨在展示使用CS32FOxx微控器,提高A/D轉化精度的應用。幫助ADC模塊用戶了解 CS32微控器提供的一些高級應用并加快開發周期。所介紹的每種模式都提供一個應用示例,以方便用戶快速移植
    發表于 05-16 14:58

    芯海應用筆記:通用 MCU 基于 IAR 芯片包 IAR9 開發指南

    幫助指導用戶針對芯海通用 MCU 基于 IAR 環境進行快速建立應用工程,快速開發,并針對常見錯誤問題,給出解決辦法。*附件:應用筆記:芯海通用MCU基于IAR芯片包IAR9開發指南.pdf
    發表于 05-16 11:52

    芯海應用筆記:通用 MCU IAR 開發指南

    本應用筆記旨在幫助指導用戶針對芯海通用 MCU 基于 IAR 環境的快速開發,幫助用戶快速建立應用工程。芯海科技通用 MCU 提供的 pack 開發包都是僅支持芯海 CSU、MDK 或 IAR 通用
    發表于 05-16 11:50

    芯海應用筆記:通用 MCU 基于 GCC 編譯開發應用

    本應用筆記旨在幫助指導用戶針對芯海通用 MCU 基于 GCC 環境的快速開發。芯海科技通用 MCU 提供的 pack 開發包都是僅支持芯海 CSU、MDK 或 IAR 通用集成的 IDE 工具,如果
    發表于 05-16 11:47

    芯海通用 MCU 應用筆記 :CS32F103 系列 MCU IAP 升級指南

    本應用筆記旨在幫助指導用戶針對芯海 CORTEX-M3 MCU CS32F103 系列單片機 IAP 應用的快速開發。本應用筆記實現了 CAN 和 USART 兩種接口方式來開發 IAP 應用,協議
    發表于 05-16 11:40

    芯海科技應用筆記:CS32F0XX TIMER外設模塊指導

    本應用筆記旨在展示使用 CS32F0xx 微控器,針對定時器外設的應用。幫助用戶了解 CS32F0xx 定時器的基本特性、操作模式及相關應用的示例代碼。提供的一些高級應用以便縮短用戶開發周期。對所介
    發表于 05-16 10:52

    芯海應用筆記:CS32F0XX ADC外設模塊指導

    本應用筆記旨在展示使用 CS32F0xx 微控器,提高 A/D 轉化精度的應用。幫助 ADC 模塊用戶了解CS32 微控器提供的一些高級應用并加快開發周期。所介紹的每種模式都提供一個應用示例,以方
    發表于 05-16 10:49

    芯海CSU18P88應用筆記

    本應用筆記旨在為用戶提供關于CSU18P88的詳細信息和使用指南,幫助用戶快速開發基于CSU18P88的應用。*附件:CSU18P88應用筆記V1.5.pdf
    發表于 05-16 10:24

    CSU18MX86應用筆記

    本應用筆記旨在為用戶提供關于CSU18MX86的詳細信息和使用指南,幫助用戶快速開發基于CSU18MX86的應用。*附件:CSU18MX86應用筆記_V1.0.pdf
    發表于 05-16 10:21

    Microchip TCP/IP 協議棧應用筆記

    電子發燒友網站提供《Microchip TCP/IP 協議棧應用筆記.pdf》資料免費下載
    發表于 04-17 14:16 ?1次下載
    主站蜘蛛池模板: 99视频免费播放| 久久天天婷婷五月俺也去| 快播dvd吧| 97在线观看免费视频| 亲胸揉胸膜下刺激视频网站APP | 欧美日韩中文国产一区| 大睾丸内射老师| 亚洲色欲色欲WWW在线丝| 男人插曲女人的视频| 国产精品麻豆高潮刺激A片| 亚洲视频国产| 热久久视久久精品2015| 国内精品自产拍在线少密芽| 96精品视频| 新新电影理论中文字幕| 女生下面免费看| 国产香蕉尹人视频在线| 99久久精品国产一区二区三区| 無码一区中文字幕少妇熟女H| 久久丫线这里只精品| 国产成人无码精品久久久影院| 中国老太性色xxxxxhd| 天天躁夜夜踩很很踩2022 | 趁老师睡着吃她的奶水| 亚洲色综合中文字幕在线| 欧美亚洲另类热图| 精品久久久久久久久免费影院| 啊轻点啊再深点视频免费| 亚洲日韩视频免费观看| 日韩精品特黄毛片免费看| 久久中文字幕乱码免费| 国产精品婷婷五月久久久久| 99久久久免费精品国产| 亚洲三级大片| 婷婷五月久久精品国产亚洲| 男生脱美女内裤内衣动态图| 狠狠色狠狠色综合日日小说| 高清国产激情视频在线观看| 97国产精品人妻无码免费| 亚洲精品国偷拍自产在线| 色婷婷亚洲五月|