2014-10-31 53 views
1

以STM32F205微控制器爲例。它具有硬件SPI接口。 SPI由多個寄存器組成。接收到的字節存儲在數據寄存器SPI-> DR中。當收到新字節時,硬件將SPI狀態寄存器SPI-> SR設置爲RXNE標誌(Rx not empy)。清除該標誌的正確方法是讀出數據寄存器SPI-> DR的內容。如果我使用臨時變量可以優化掉(因爲它不使用):如何確保微控制器外設寄存器已被讀取

uint8_t foo = SPI1->DR; 

我看到了嵌入式軟件的另一個不尋常的事情,但我不知道它是否是正確的:

(void)SPI1->DR; 

所以我正在尋找如何確保數據寄存器在高優化級別下被讀取的方法。

回答

1

您可以使用volatile關鍵字來防止不必要的優化。

volatile uint8_t foo = SPI1->DR; 

爲了避免編譯器警告,你可以做以下

(void)foo; 
+0

在這種情況下,我會得到一個不需要的編譯器的警告(foo是asigned value但未使用)。 – Max 2014-10-31 08:40:07

+0

我更新了我的評論 – 2014-10-31 08:48:30

+0

其實我並不需要數據庫的價值。我必須閱讀它才能使硬件清除RXNE標誌。賦值給一個變量只是一個最簡單的方法。 – Max 2014-10-31 08:50:38

0

通常SPI RX狀態標誌由兩個清除寫着:你讀數據寄存器,但你還需要讀狀態寄存器知道實際狀態。由於讀取數據寄存器會清除標誌,因此您需要先讀取狀態寄存器。

爲了確保存在不正確的行爲並且沒有生成不正確的代碼,我強烈建議將狀態和數據寄存器的讀取放在代碼中彼此相鄰。

爲了避免代碼被優化掉,使用聲明爲volatile的局部變量。

volatile uint8_t sr = SRI1->SR; 
volatile uint8_t dr = SPI1->DR; 

// do stuff with sr and dr 

(void) dr; // if not interested in the received data 
1

一個簡單的方法是將讀取放在單獨編譯的文件中。一個文件具有讀取的函數,返回值讀取,不能優化,必須這樣做。另一個文件調用該函數,但不使用返回值,不能優化。在這種情況下,你需要花費相當便宜的函數調用,但在你使用llvm或類似的東西來優化整個項目之前,它不能優化讀取。

另一種解決方法是用匯編語言做一個簡單的ldr r0,[r0],bx lr函數,把它傳遞給它的地址。如上所述,因爲它位於單獨的編譯/優化域中,所以無法優化。

0

它不會被優化掉,因爲SPI1-> DR應該被聲明爲volatile

2

頭文件中的所有硬件寄存器都被聲明爲volatile,所以讀取將從不會被優化掉。你展示的結構 - (void)SPI1->DR;(void)部分實際上是多餘的)就是這樣 - 讀操作不會被優化,所以你可以安全地使用它,這是最好的選擇 - 沒有無用的臨時變量。這與您有時看到的東西類似,如(void)0;